2015-12-02 50 views
0

我最近參加了面試,面試官問我關於HashMapConcurrentHashMap的問題。在最初的線程安全優勢之後,我說它在遍歷時不會拋出ConcurrentModificationException,而不是HashMapConcurrentHashMap是否自己創建副本?

面試官繼續問我爲什麼不扔它。我說內部HashMap有一個變量modCount,它保留對地圖所做的修改次數,Iterator正在比較這個數字和它在創建時被初始化的數字。如果這個數字不同,它會拋出一個異常,這個比較不會發生在ConcurrentHashMap

然後他說ConcurrentHashMap會在遍歷時自己複製一份。

我對這個說法有所懷疑,因爲以前沒有遇到過這個。即使閱讀文檔也沒有給我足夠的答案。

它會在任何時候複製(讀或寫)?

+2

* ConcurrentHashMap在遍歷時會自己創建副本* - 他錯了。查看源代碼 –

+0

'然後他說ConcurrentHashMap將在遍歷時自己創建一個副本。'任何不在javadoc中的都是純粹的bs。其他實施細節可能在某個時間點是真實的,但不能獲得如此強有力的聲明。 – UmNyobe

+1

我希望你沒有得到這份工作。 – UmNyobe

回答

1

不,它與製作任何副本無關。並且沒有投擲ConcurrentModificationException未必在多線程環境下。

有關您的問題的幾點。

  1. ConcurrentModificationException與併發性(和它實際上有一個壞名字)無關。當您迭代某個數據結構時會拋出它,並且在對結構進行一些修改後再次使用迭代器。這被稱爲fail fast的行爲。由於這種行爲,它可以在多線程環境下拋出,但完全沒有依賴性。

  2. ConcurrentHashMap是一個精緻的結構,我建議你通讀它。它實現併發的方式是通過

    • 任何地圖中的訪問不同的桶線程自然分開所以沒必要除了老調重彈的情況下它們之間的同步。

    • 對於訪問同一個存儲桶的線程,如果存儲桶是空的,則它使用CAS即AtomicReference訪問存儲桶中唯一的元素。

    • 如果正在運行的存儲桶存在散列衝突並且具有多個元素,則其保留爲鏈接列表(除了將鏈接列表重新鏈接到二叉樹以在極端散列衝突下實現更好性能的JDK 1.8的情況)。鏈接列表的好處是它自然地支持併發性,只要您以CAS方式對下一個指針進行操作即可。

還有大量的編碼在ConcurrentHashMap藝術的,所以我建議你仔細閱讀它的源代碼。

相關問題