2013-04-10 88 views
1

只看了一下CopyOnWriteArrayList类,我想知道为什么它的get(...)方法不需要任何同步。 add(...)和set(...)方法使用ReentrantLock更改互斥块中的基础数组。但get(...)只是返回未经过同步的原始底层数组。好吧,底层数组声明为volatile:为什么CopyOnWriteArrayList.get不需要同步?

private volatile transient Object[] array; 

但是我不明白如何使用volatile使得任何同步都是多余的。它只会阻止编译器缓存存储在数组中的引用。如果我明白了为什么这里不需要同步我可以写我的代码比以前少一些锁争...

感谢,奥利弗

+6

该班的名字是一个提示。 – 2013-04-10 13:11:17

+2

可能的副本[如何CopyOnWriteArrayList线程安全?](http://stackoverflow.com/questions/2950871/how-can-copyonwritearraylist-be-thread-safe) – 2013-04-10 13:12:02

+0

@Mark Rotteveel:你是对的。谢谢。 – OlliP 2013-04-10 13:17:23

回答

1

的线索是在名称(如MarkRotteveel指出)。

如果发生任何更改,则在单独的Object[]中进行更改,然后通过“复制写入”复制整个批次。

由于内部Object[]volatile当参考从旧Object[]更改为新Object[]的变化是由所有线程回升。

1

它使用一个小“绝招” - 当底层数组改变了,事件的顺序是:

  1. 创建一个新的阵列
  2. 填充新的阵列
  3. 变化所持参考指向新阵列的类

第三步写入private volatile transient Object[] array; - 由于存在易失性语义,所以在第三步之前所做的所有更改都变为可见。

所以不仅是新的参考可见,但新阵列的内容也可见(这是诀窍)。