2014-06-13 95 views
2

我需要問一下ConcurrentHashMap的下面幾個方面,因爲我無法從源代碼中找出它。
(請注意,我不是問的行爲,這是很好理解的,其有關機制的迭代器採用顯示行爲)Concurrenthashmap迭代器數據結構

"The iterator is guaranteed to reflect the state of the map at the time of it's creation." 

1.Does這意味着迭代器獲取自己的副本的支持地圖? 即使在創建迭代器之後,爲什麼volatile讀取不會給出'value'的真實狀態呢? (代碼的確切位置將被讚賞)

2.即使段正在進行重新散列,非阻塞式讀取和迭代如何設法保持一致?

+0

那麼,如果某個段正在進行重新散列,那麼這意味着該映射在結構上被修改了,並且根據javadoc迭代器不會*在創建它們之後反映修改。但如果他們這樣做,我不知道他們是如何工作的。另外,我真的很想說我以前看過類似的東西,但我不完全確定... – awksp

+0

你從哪裏得到這個報價?我不相信ConcurrentHashMap行爲是「很好理解」的:ConcurrentHashMap的迭代器是*弱一致的* ... javadoc指出:「迭代器和枚舉返回反映散列表在某時的狀態或在迭代器/枚舉的創建「。 –

回答

1

正如在評論中提到的,我不相信ConcurrentHashMap行爲是「很好理解」。對於ConcurrentHashMap,您的未引用引用中的斷言不是真的。

的ConcurrentHashMap的迭代器是弱一致 ... javadoc的狀態:

迭代器,Spliterators和枚舉的或自創建以來回報在某一點反映了哈希表的狀態元素迭代器/枚舉的

鑑於此,

簡短的回答你的問題1:沒有,它沒有得到其自身的副本地圖

簡短的回答你的問題2 : 「行爲一致」


^h ERE是從幫助解釋執行的javadoc一些其他相關報價:

的基本策略是細分細分中的表,它的每一個本身是一個同時讀取哈希表...

段維護一個始終保持一致狀態的條目列表表,因此可以在不鎖定的情況下讀取(通過對段和表的易失性讀取)。這需要在調整表格大小時根據需要複製節點,以便仍舊使用舊版表格的讀者遍歷舊列表。

在其rehash方法中,每個Segment都會發生節點複製。 Segment.rehash()方法的javadoc解釋了功能:

將每個列表中的節點重新分類爲新表。因爲我們使用兩次冪次展開,所以每個箱的元素必須保持相同的索引,或者以兩個偏移的冪移動。我們通過捕獲舊節點可以重用的情況來消除不必要的節點創建,因爲它們的下一個字段不會改變。統計上,在默認閾值下,當表格翻倍時,只有約1/6需要克隆。只要它們不再被可能位於同時遍歷表中的讀者線程引用,它們替換的節點就會成爲垃圾收集器。條目訪問使用普通數組索引,因爲它們之後是易失性表寫。

請參閱Richard Burnison's excellent article爲ConcurrentHashMap的實現細節很好地概括描述了JDK 7


欲瞭解更多信息:

Javadocs for ConcurrentHashMap jdk8

Source code for ConcurrentHashMap (openjdk-7)

ConcurrentHashMap returns a weakly consistent iterator, why should we use it anyhow?