深入研究JDK并发集合类-CopyOnWriteArrayList

很多场景中都是读远远高于写操作,那么每次对读取进行加锁其实是一种资源浪费.根据读写锁的思想,读锁和读锁之间不冲突. 
但是读操作会受到写操作的阻碍,在写操作发生时,读就必须等待,否则可能读到不一致的数据.同理读操作正在进行的时候, 
程序也不能进行写入. 
JDK提供了CopyOnWriteArrayList类,读取是完全不加锁的,并且写入也不会阻塞读取操作,这样一来性能大大提升了. 
其实,就是在写操作时,进行一次自我复制,当List需要修改时,并不修改原有内容(这对于保证当前读线程的数据一致性非常重要) 
而对原内容进行一次复制,将修改内容写入副本.写完后,再将修改完的副本替换原来的操作.这就保证了写操作不会影响读了.

public class CopyOnWriteArrayList<E>

    implements List<E>, RandomAccess, Cloneable, java.io.Serializable {

 

    final transient ReentrantLock lock = new ReentrantLock();

 

    private transient volatile Object[] array;

原文:https://blog.csdn.net/lan861698789/article/details/81323724

    final void setArray(Object[] a) {

        array = a;

    }

 

    //关于读取的实现(不上锁):

    final Object[] getArray() {

        return array;

    }

    private E get(Object[] a, int index) {

 

        return (E) a[index];

    }

 

    public E get(int index) {

        return get(getArray(), index);

    }

 

    //其他代码

    .......

原文:https://blog.csdn.net/lan861698789/article/details/81323724

    //写入操作:

    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;

            //替换老的数组,并且读线程可以立即"察觉",因为array变量是volatile类型

            setArray(newElements);

            return true;

        } finally {

            lock.unlock();

        }

}

public boolean addAll(Collection<? extends E> c) {

    Object[] cs = c.toArray();

    if (cs.length == 0)

        return false;

    final ReentrantLock lock = this.lock;

    lock.lock();

    try {

        Object[] elements = getArray();

        int len = elements.length;

        Object[] newElements = Arrays.copyOf(elements, len + cs.length);

        System.arraycopy(cs, 0, newElements, len, cs.length);

        setArray(newElements);

        return true;

    } finally {

        lock.unlock();

    }

}

}

原文:https://blog.csdn.net/lan861698789/article/details/81323724

分析:

和基础arrayList不同:ArrayList每次都会扩容,而copyOnWriteArrayList每次只增加一个or要增加的length长度。

一句话:CopyOnWriteArrayList读不加锁,写才加锁.

Collections.synchronizedList读写都加锁.

猜你喜欢

转载自blog.csdn.net/lan861698789/article/details/81323724