java多线程:CopyOnWriteArrayList

本文是对该博文的延伸

为什么CopyOnWriteArrayList 可以不使用checkForComodification()呢?

首先,CopyOnWriteArrayList 的迭代器在创建时是将数组中的元素复制了一遍的

然后,CopyOnWriteArrayList 的add等操作也是copy一份现有数据,在现有数据上修改好,在把原有数据的引用改成指向修改后的数据。还加上了同步锁以避免多线程同时add

public boolean addAll(int index, Collection<? extends E> c) {
            synchronized(CopyOnWriteArrayList.this.lock) {
                this.rangeCheckForAdd(index);
                Object[] oldArray = this.getArrayChecked();
                boolean modified = CopyOnWriteArrayList.this.addAll(this.offset + index, c);
                this.size += (this.expectedArray = CopyOnWriteArrayList.this.getArray()).length - oldArray.length;
                return modified;
            }
        }

相当于读写都是copy之后对副本进行的,而不直接对源数组进行。此外,数组还被声明为了volatile类型,这会要求,当线程 2 进行修改时,会导致线程 1 的工作内存中的缓存变量的缓存行无效(反映到硬件层的话,就是 CPU 的 L1 或者 L2 缓存中对应的缓存行无效):

private transient volatile Object[] array;

这样做的话,对数组的修改就能在完成后同步到各个线程中,但是并不会直接影响线程中正在进行的利用迭代器的读(不会同时写的,有同步锁),因为读的是副本,不会过期,所以可以正常地继续从工作空间中间读自己拷贝的副本,虽然工作空间中的CopyOnWriteArrayList 变量已经过期了。但是此时读的就不是最新的内容了,所以说CopyOnWriteArrayList保证的是弱一致性

这是我个人的理解,如有错误希望指正

posted @ 2020-03-10 12:11  别再闹了  阅读(544)  评论(0编辑  收藏  举报