Concurrenthashmap迭代器数据结构

时间:2014-06-13 03:43:53

标签: java collections concurrenthashmap

我需要询问ConcurrentHashMap的以下方面,因为我无法从源代码中找出它。
(请注意,我不是在询问行为,这是很好理解的。它是关于迭代器用来显示行为的机制)

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

1.这是否意味着迭代器获得了自己的支持映射副本? 为什么其他不稳定的读取不会给出真正的“价值”状态' ,即使在创建迭代器之后? (代码的确切位置将不胜感激)

2.即使片段正在进行重新散列,非阻塞读取和迭代如何设置为一致的行为?

1 个答案:

答案 0 :(得分:1)

正如评论中所提到的,我不相信ConcurrentHashMap行为是“很好理解”的。对于ConcurrentHashMap,您的未归因引用中的断言不正确。

ConcurrentHashMap的迭代器弱一致 ... javadoc声明:

  

Iterators,Spliterators和Enumerations在迭代器/枚举的创建时或之后的某个时刻返回反映哈希表状态的元素。

鉴于此,

问题1的简短回答是:不,它没有自己的地图副本

问题2的简短回答是: “行为一致”


以下是来自javadocs的一些其他相关引用,有助于解释实现:

  

基本策略是在Segments中细分表,每个表本身都是一个可同时读取的哈希表......

     

分段维护一个始终保持一致状态的条目列表,因此可以在不锁定的情况下读取(通过段和表的易失性读取)。这需要在表调整大小期间在必要时复制节点,因此仍然使用旧版表的读者可以遍历旧列表。

在其rehash方法中为每个Segment进行节点复制。 Segment.rehash()方法的javadoc解释了功能:

  

将每个列表中的节点重新分类为新表。因为我们使用的是二次幂扩展,所以每个bin的元素必须保持相同的索引,或者以两个偏移的幂移动。我们通过捕获旧节点可以重用的情况来消除不必要的节点创建,因为它们的下一个字段不会改变。从统计上看,在默认阈值下,当表格翻倍时,只有大约六分之一的人需要克隆。一旦它们不再被可能同时遍历表中的任何读取器线程引用,它们替换的节点将是可垃圾收集的。条目访问使用普通数组索引,因为它们之后是volatile表写入。

请参阅Richard Burnison's excellent article以获取有关jdk 7的ConcurrentHashMap实现细节的详细概述。


更多信息:

Javadocs for ConcurrentHashMap jdk8

Source code for ConcurrentHashMap (openjdk-7)

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