zoukankan      html  css  js  c++  java
  • CopyOnWriteArrayList与Collections.synchronizedList

    1、CopyOnWriteArrayList

    1.CopyOnWriteArrayList(字译名称:写时复制),它可以看成是线程安全且读操作无锁的ArrayList。

    2.使用场景:

    读操作远远大于写操作,比如有些系统级别的信息,往往需要加载或者修改很少的次数,但是会被系统内的所有模块频繁的访问。

    3.原理:

    CopyOnWriteArrayList容器允许并发读,读操作时无锁的,性能高。写操作,比如向容器中添加一个元素,则首先将当前容器复制一份,然后在新的副本上执行写操作(此时仍然可以读取,读取的时旧的容器中的数据),结束之后再将原容器的引用指向新容器。

    特点:这种链表,读取完全不用加锁,写入也不会阻塞读取,只有写入和写入之间需要进行同步等待。

    缺点:1)占用内存,每次执行写操作都要将原容器拷贝一份,数据量大时,对内存压力较大,可能会引起频繁GC

               2)无法保证实时性,Vector对于读写操作都同步,保证了读和写的一致性,但是CopyOnWriteArrayList,写和读分别作用在新老不同的容器上,在写的过程中,读不会阻塞,但是读取到的是老容器的数据。

    CopyOnWriteArrayList在线程对其进行些操作的时候,会拷贝一个新的数组以存放新的字段。其写操作的代码如下:

    /** The lock protecting all mutators */  
        transient final ReentrantLock lock = new ReentrantLock();  
      
        /** The array, accessed only via getArray/setArray. */  
        private volatile transient Object[] array;//保证了线程的可见性  
          
         public boolean add(E e) {  
        final ReentrantLock lock = this.lock;//ReentrantLock 保证了线程的可见性和顺序性,即保证了多线程安全。  
        lock.lock();  
        try {  
            Object[] elements = getArray();  
            int len = elements.length;  
            Object[] newElements = Arrays.copyOf(elements, len + 1);//在原先数组基础之上新建长度+1的数组,并将原先数组当中的内容拷贝到新数组当中。  
            newElements[len] = e;//设值  
            setArray(newElements);//对新数组进行赋值  
            return true;  
        } finally {  
            lock.unlock();  
        }  
    }
    View Code

    2、Collections.synchronizedList

    2.1ArrayList

      ArrayList是非线性安全,此类的 iterator 和 listIterator 方法返回的迭代器是快速失败的:在创建迭代器之后,除非通过迭代器自身的 remove 或 add 方法从结构上对列表进行修改,否则在任何时间以任何方式对列表进行修改,迭代器都会抛出 ConcurrentModificationException。即在一方在便利列表,而另一方在修改列表时,会报ConcurrentModificationException错误。而这不是唯一的并发时容易发生的错误,在多线程进行插入操作时,由于没有进行同步操作,容易丢失数据。因此,在开发过程当中,ArrayList并不适用于多线程的操作。

    2.2Vector

      从JDK1.0开始,Vector便存在JDK中,Vector是一个线程安全的列表,采用数组实现。其线程安全的实现方式是对所有操作都加上了synchronized关键字,这种方式严重影响效率,因此,不再推荐使用Vector了。

    2.3Collections.synchronizedList

      CopyOnWriteArrayList和Collections.synchronizedList是实现线程安全的列表的两种方式。两种实现方式分别针对不同情况有不同的性能表现,其中CopyOnWriteArrayList的写操作性能较差,而多线程的读操作性能较好。而Collections.synchronizedList的写操作性能比CopyOnWriteArrayList在多线程操作的情况下要好很多,而读操作因为是采用了synchronized关键字的方式,其读操作性能并不如CopyOnWriteArrayList。因此在不同的应用场景下,应该选择不同的多线程安全实现类。

    Collections.synchronizedList的源码可知,其实现线程安全的方式是建立了list的包装类,代码如下:

    public static <T> List<T> synchronizedList(List<T> list) {  
    return (list instanceof RandomAccess ?  
                   new SynchronizedRandomAccessList<T>(list) :  
                   new SynchronizedList<T>(list));//根据不同的list类型最终实现不同的包装类。  
    } 
    View Code

    其中,SynchronizedList对部分操作加上了synchronized关键字以保证线程安全。但其iterator()操作还不是线程安全的。部分SynchronizedList的代码如下:

    public E get(int index) {  
            synchronized(mutex) {return list.get(index);}  
            }  
        public E set(int index, E element) {  
            synchronized(mutex) {return list.set(index, element);}  
            }  
        public void add(int index, E element) {  
            synchronized(mutex) {list.add(index, element);}  
            }  
        public ListIterator<E> listIterator() {  
            return list.listIterator(); // Must be manually synched by user 需要用户保证同步,否则仍然可能抛出ConcurrentModificationException  
            }  
      
        public ListIterator<E> listIterator(int index) {  
            return list.listIterator(index); // Must be manually synched by user <span style="font-family: Arial, Helvetica, sans-serif;">需要用户保证同步,否则仍然可能抛出ConcurrentModificationException</span>  
    }  
    View Code
    写操作:在线程数目增加时CopyOnWriteArrayList的写操作性能下降非常严重,而Collections.synchronizedList虽然有性能的降低,但下降并不明显。
    读操作:在多线程进行读时,Collections.synchronizedList和CopyOnWriteArrayList均有性能的降低,但是Collections.synchronizedList的性能降低更加显著。
     
  • 相关阅读:
    「联赛模拟测试33」题解
    分享几个基于vue的移动端框架
    11-15
    test
    联赛模拟测试20 C. Weed
    联赛模拟测试20 D. Drink
    联赛模拟测试24 联合权值·改
    联赛模拟测试21 表格
    近期的一些考试题目
    shell脚本执行错误 $' ':command not found
  • 原文地址:https://www.cnblogs.com/yanmingyuan/p/10555138.html
Copyright © 2011-2022 走看看