Java 为什么CopyOnWriteArrayList.get不需要同步?
刚看了CopyOnWriteArrayList类,我想知道为什么它的get(…)方法不需要任何同步。add(…)和set(…)方法使用ReentrantLock更改互斥块中的基础数组。但是get(…)只返回原始的底层数组,没有任何同步。好的,底层数组声明为volatile:Java 为什么CopyOnWriteArrayList.get不需要同步?,java,locking,volatile,java.util.concurrent,Java,Locking,Volatile,Java.util.concurrent,刚看了CopyOnWriteArrayList类,我想知道为什么它的get(…)方法不需要任何同步。add(…)和set(…)方法使用ReentrantLock更改互斥块中的基础数组。但是get(…)只返回原始的底层数组,没有任何同步。好的,底层数组声明为volatile: private volatile transient Object[] array; 但我不认为使用volatile会使任何同步变得多余。它只防止编译器缓存存储在数组中的引用。如果我理解为什么这里不需要同步,我可以用比以前
private volatile transient Object[] array;
但我不认为使用volatile会使任何同步变得多余。它只防止编译器缓存存储在数组中的引用。如果我理解为什么这里不需要同步,我可以用比以前更少的锁争用来编写代码
谢谢,奥利弗,线索就在名字里(正如马克·罗特维尔所指出的)
当进行任何更改时,在单独的对象[]
中进行更改,然后复制整个批次-“写入时复制”
当引用从旧的对象[]
更改为新的对象[]
时,内部对象[]
是易变的,因此所有线程都会进行更改。它使用了一个小“技巧”-当底层数组更改时,事件序列是:
private volatile transient Object[]数组代码>-由于易变语义,在第三步之前所做的所有更改都是可见的
因此,不仅新引用可见,而且新数组的内容也可见。(这就是诀窍)。类的名称是一个提示。@Mark rotterveel的可能重复:你是对的。谢谢。@MarkRotteveel我认为这篇文章中被接受的答案忽略了一个要点。另一个答案更准确。重复马克·罗特维尔指出的