美文网首页JavaJava 并发编程
Java 并发系列四:CopyOnWriteArrayList

Java 并发系列四:CopyOnWriteArrayList

作者: 逗逼程序员 | 来源:发表于2019-09-19 21:14 被阅读0次

    When

    CopyOnWriteArrayList 是jdk1.5以后并发包中提供的一种并发容器,写操作通过创建底层数组的新副本来实现,是一种读写分离的并发策略,我们也成为“写时复制容器”,类似的容器还有 CopyOnWriteArraySet。

    Why

    众所周知,集合框架中的ArrayList 是非线程安全的,Vector虽然是线程安全的,但是处理方式简单粗暴(synchronized),性能较差。而CopyOnWriteArrayList提供了不同的处理并发的思路。

    How

    很多时候,我们系统中处理的都是读多写少的并发场景。CopyOnWriterArrayList 允许并发的读,读操作是无锁的,性能较高。写操作的话,比如向容器增加一个元素,则首先将当前容器复制一份,然后在新副本上执行写操作,结束之后再将原容器的引用指向新容器。

    img

    优缺点分析

    了解了CopyOnWriteArrayList原理,接下来分析优缺点及使用场景

    优点:

    读操作性能很高,因为无需任何同步措施,比较适用于读多写少的并发场景。Java 的 list 在遍历时,若中途有其他线程对容器进行修改,则会抛出ConcurrentModificationException 异常。而CopyOnWriteArrayList由于其“读写分离”的思想,遍历和修改操作分别作用在不同的 list容器,所以迭代的时候不会抛出 ConcurrentModificationExecption 异常了。

    缺点:

    缺点也很明显,一是内存占用问题,毕竟每次执行写操作都要将原容器拷贝一份,数据量大时,对内存压力较大,甚至可能引起频繁GC,二是无法保证实时性,Vector 对读写操作均加锁同步,可以保证容器的读写强一致性,CopyOnWriteArrayList由于其实现策略的原因,写和读分别作用于不容容器上,在写的过程中,读是不会发生阻塞的,未切换索引置新容器时,是读不到刚写入的数据的。

    源码分析

    原理理解了,再来分析源码吧~~~~~

    public boolean add(E e) {
       //加锁,对写操作保证线程安全
       final ReentrantLock lock = this.lock;
       lock.lock();
       try {
           Object[] elements = getArray();
           int len = elements.length;
           //拷贝原容器,长度为原容器+1
           Object[] newElements = Arrays.copyOf(elements, len + 1);
           //在新副本执行添加操作
           newElements[len] = e;
           //底层数组指向新的数组
           setArray(newElements);
           return true;
       } finally {
           lock.unlock();
       }
    }
    其中 底层数组定义如下:
    private transient volatile Object[] array;
    增加内存可见性。
    

    同理可以分析删除操作。

    总结

    其实并发容器的优缺点,是要根据我们实际的业务场景做出取舍的。

    但前提是,你要了解他们各自的优缺点,谢谢!

    再一次感谢作者!!

    https://www.cnblogs.com/chengxiao/p/6881974.html

    相关文章

      网友评论

        本文标题:Java 并发系列四:CopyOnWriteArrayList

        本文链接:https://www.haomeiwen.com/subject/rbtductx.html