zoukankan      html  css  js  c++  java
  • CopyOnWriteArrayList

    文章摘抄自http://www.cnblogs.com/xrq730/p/5020760.html

    1.CopyOnWriteArrayList位于java.util.concurrent包下,这个类为并发而设计

    2.CopyOnWriteArrayList,写入时复制.另外的线程对这个list写入时,包括add,set,remove时,都会复制一个副本数组,对这个副本进行写入.

    3.允许空,有序,可重复,线程安全

    4.源代码

    public class CopyOnWriteArrayList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
        private static final long serialVersionUID = 8673264195747942595L;
     
        /** The lock protecting all mutators */
        transient final ReentrantLock lock = new ReentrantLock();
     
        /** The array, accessed only via getArray/setArray. */
        private volatile transient Object[] array;
        ...
    }
    
    public CopyOnWriteArrayList() {
        setArray(new Object[0]);
    }
    
    final void setArray(Object[] a) {
        array = a;
    }
    

    5.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();
    }
    }  

    加锁.

    拿到原数组,得到新数组的大小(原数组大小+1),实例化出一个新的数组来把原数组的元素复制到新数组中去

    新数组最后一个位置设置为待添加的元素(因为新数组的大小是按照原数组大小+1来的)

    把Object array引用指向新数组

    解锁

    6.注意

    CopyOnWriteArrayList的缺点,就是修改代价十分昂贵,每次修改都伴随着一次的数组复制;但同时优点也十分明显,就是在并发下不会产生任何的线程安全问题

    读写分离

    我们读取CopyOnWriteArrayList的时候读取的是CopyOnWriteArrayList中的Object[] array,但是修改的时候,操作的是一个新的Object[] array,读和写操作的不是同一个对象,这就是读写分离。这种技术数据库用的非常多,在高并发下为了缓解数据库的压力,即使做了缓存也要对数据库做读写分离,读的时候使用读库,写的时候使用写库,然后读库、写库之间进行一定的同步,这样就避免同一个库上读、写的IO操作太多

    最终一致

    对CopyOnWriteArrayList来说,线程1读取集合里面的数据,未必是最新的数据。因为线程2、线程3、线程4四个线程都修改了CopyOnWriteArrayList里面的数据,但是线程1拿到的还是最老的那个Object[] array,新添加进去的数据并没有,所以线程1读取的内容未必准确。不过这些数据虽然对于线程1是不一致的,但是对于之后的线程一定是一致的,它们拿到的Object[] array一定是三个线程都操作完毕之后的Object array[],这就是最终一致。最终一致对于分布式系统也非常重要,它通过容忍一定时间的数据不一致,提升整个分布式系统的可用性与分区容错性。当然,最终一致并不是任何场景都适用的,像火车站售票这种系统用户对于数据的实时性要求非常非常高,就必须做成强一致性的。

      

  • 相关阅读:
    Xshell添加快捷按钮
    Go语言基础之21--反射
    Jenkins自动化CI CD流水线之7--流水线自动化发布PHP项目
    Jenkins自动化CI CD流水线之6--构建邮件状态通知
    Jenkins自动化CI CD流水线之5--pipeline
    Python练习-函数(方法)的定义和应用
    Python文件操作-文件的增删改查
    Python练习-不知道弄个什么鬼
    Python练习-短小精干版三级"片儿"
    Python练习-三级菜单与"片儿"无关!
  • 原文地址:https://www.cnblogs.com/cbySense/p/7098601.html
Copyright © 2011-2022 走看看