CopyOnWriterArrayList 避免 fail-fast 的机制是写线程拷贝一个 ArrayList,在这个拷贝的对象上进行修改 修改后再把对象赋值给原本的引用,而读线程则在原有的对象上操作
我想,如果写线程把新对象赋值给原引用后,那读线程不是一样面临着对象被修改的状况,从而有可能抛出出 ConcurrentMOdificationException 吗?
1
wwqgtxx 2017-03-25 13:26:56 +08:00 via iPhone
重点在于“写线程把新对象赋值给原引用后”,之前那个读线程拿到的迭代器依然是之前的旧 arraylist 呀,所以并不会触发 ConcurrentMOdificationException
|
2
SoloCompany 2017-03-25 17:45:25 +08:00
COW 或者叫 double buffer 机制的关键在于任何时候读取到的都是一个完整的 snapshot
这个 snapshot 是什么时候产生的呢? 如果你所理解的 read 仅仅是 get 操作,那么仅针对 ArrayList 数据结构而言,根本不需要 COW 也永远不会发生 ConcurrentModificationException 。 需要 snapshot 的是 iterator , COW 机制是保证你任何时候得到一个 iterator 它的状态都是永远不变的也永远不会因为并发而产生异常,而 failfast 机制则是相反,是在检测出并发修改的时候尽早抛出异常 |
3
esolve OP @SoloCompany 譬如用 iterator 循环体里面读啊
或者 for(i) list(i).get 里读 |
4
SoloCompany 2017-03-27 12:52:50 +08:00
index base loop 一般而言就永远不可能发生 ConcurrentModificationException
index base loop 不可能支持 failfast 的, COW 也不会对并发有任何帮助 所有并发冲突会导致的任意错误都可能发生,包括且不限于 - IndexOutOfBoundException (结尾处的元素被 remove 了) - 一个元素被完全跳过了(中间元素删除后,下标错误导致跳过了更多的元素) - 一个元素被遍历多次(中间插入新元素,下标变化导致前面的元素又被遍历了一次) |
5
esolve OP @SoloCompany 譬如用 iterator 循环体里面读总会产生 ConcurrentModificationException 了吧
|
6
SoloCompany 2017-03-27 16:34:37 +08:00 via iPhone
@esolve 我只能回答 rtfm 了,请多读 javadoc
|