本文是对该博文的延伸
为什么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保证的是弱一致性
这是我个人的理解,如有错误希望指正