2013-04-10 85 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; - 由於存在易失性語義,所以在第三步之前所做的所有更改都變爲可見。

所以不僅是新的參考可見,但新陣列的內容也可見(這是訣竅)。