并发编程

JAVA并发容器-写时复制容器

2019-07-31  本文已影响17人  xiaolyuh

写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。

这样做的好处是我们可以对容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以写时复制容器也是一种读写分离的思想,读和写不同的容器。如果读的时候有多个线程正在向容器添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的,只能保证最终一致性

适用读多写少的并发场景,常见应用:白名单/黑名单, 商品类目的访问和更新场景。

CopyOnWriteArrayList和CopyOnWriteArraySet就是写时复制容器。

CopyOnWriteArrayList 类图

CopyOnWriteArrayList.png

底层依然是数组,基于ReentrantLock来做并发控制。

add()

    public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        // 加锁
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
             // 复制原数组
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            // 添加元素
            newElements[len] = e;
            // 替换数组
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

CopyOnWriteArraySet类图

CopyOnWriteArraySet.png

CopyOnWriteArraySet就是基于CopyOnWriteArrayList来实现的。

测试方法

    @Test
    public void testCopyOnWrite() {
        CopyOnWriteArrayList<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
        copyOnWriteArrayList.add(5);
        copyOnWriteArrayList.add(3);
        copyOnWriteArrayList.add(4);
        copyOnWriteArrayList.add(2);
        copyOnWriteArrayList.add(3);

        System.out.println(copyOnWriteArrayList);

        CopyOnWriteArraySet<Integer> copyOnWriteArraySet = new CopyOnWriteArraySet<>();
        copyOnWriteArraySet.add(5);
        copyOnWriteArraySet.add(3);
        copyOnWriteArraySet.add(4);
        copyOnWriteArraySet.add(2);
        copyOnWriteArraySet.add(3);

        System.out.println(copyOnWriteArraySet);
    }

输出:

[5, 3, 4, 2, 3]
[5, 3, 4, 2]

源码

https://github.com/wyh-spring-ecosystem-student/spring-boot-student/tree/releases

spring-boot-student-concurrent 工程

layering-cache

为监控而生的多级缓存框架 layering-cache这是我开源的一个多级缓存框架的实现,如果有兴趣可以看一下

上一篇 下一篇

猜你喜欢

热点阅读