繁体   English   中英

Concurrenthashmap迭代器数据结构

[英]Concurrenthashmap Iterator data structure

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

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

1.这是否意味着迭代器获得了自己的备份映射副本? 为什么即使在创建迭代器之后,易失性读取也无法给出“值”的真实状态? (代码的确切位置将不胜感激)

2.即使段正在进行重新哈希处理,无阻塞读取和迭代如何仍能保持一致的行为?

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

ConcurrentHashMap的迭代器是弱一致性的 ... Javadoc指出:

迭代器,拆分器和枚举返回的元素反映了在创建迭代器/枚举时或此后某个时刻哈希表的状态。

有鉴于此,

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

对问题2的简短回答是: 不是 “表现一致”


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

基本策略是将表细分为细分,细分本身就是一个并发可读的哈希表...

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

节点复制以其重新哈希方法针对每个段发生。 Segment.rehash()方法的javadocs解释了该功能:

将每个列表中的节点重新分类为新表。 因为我们使用的是2的幂次展开,所以每个bin中的元素必须保持相同的索引或以2个偏移量的幂移动。 通过捕获旧节点因为其下一个字段不会更改而可以重复使用的情况,我们消除了不必要的节点创建。 统计上,在默认阈值下,当表加倍时,仅其中的六分之一需要克隆。 一旦它们被并发遍历表中的任何读取器线程不再引用,它们替换的节点将立即被垃圾回收。 条目访问使用纯数组索引,因为它们后面是易失表写入。

请参阅Richard Burnison的精彩文章 ,以更好地概述针对jdk 7的ConcurrentHashMap的实现细节。


了解更多信息:

用于ConcurrentHashMap jdk8的Javadocs

ConcurrentHashMap(openjdk-7)的源代码

ConcurrentHashMap返回一个弱一致性迭代器,为什么我们还是应该使用它呢?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM