并发Hashmap - 失败安全问题

Kau*_*shi 4 java hashmap concurrenthashmap concurrentmodification

我正在尝试使用故障保护的示例ConcurrentHashMap.

下面是我试过的示例片段..

ConcurrentHashMap<String, String> cMap = new ConcurrentHashMap<String, String>();
cMap.put("1", "Windows Phone");
cMap.put("2", "iPhone");
cMap.put("3", "HTC");

Iterator iterator=cMap.keySet().iterator();

while (iterator.hasNext()) {
    System.out.println(cMap.get(iterator.next()));
    cMap.put("Samsung", "S5");
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Windows Phone
HTC
iPhone
Run Code Online (Sandbox Code Playgroud)

这是我理解的一个故障保护示例.

但是当我尝试下面的例子时,我得到了不同的输出.

ConcurrentHashMap<String, String> cMap = new ConcurrentHashMap<String, String>();
cMap.put("1", "Windows Phone");
cMap.put("2", "iPhone");
cMap.put("3", "HTC");

Iterator iterator=cMap.keySet().iterator();

while (iterator.hasNext()) {
    System.out.println(cMap.get(iterator.next()));
    cMap.put("4", "S5");
}
Run Code Online (Sandbox Code Playgroud)

输出是

Windows Phone
HTC
S5
iPhone
Run Code Online (Sandbox Code Playgroud)

上面两个代码片段之间有什么区别.在第二个代码片段中,我添加了cMap.put("4","S5"); 而这正在增加.但是在fisrt片段中,我添加了cMap.put("三星","S5"); 这没有被添加到ConcurrentHashmap.我是否犯了任何错误或者其他可能是这种不同输出的原因.

提前致谢.

Sim*_*nni 13

与非并发hashmap相反,并发映射如果在迭代时添加内容,则不会快速失败.

但是,无法保证迭代器(或get()方法或任何其他读取操作)何时以及是否将看到新添加/删除的元素.

从文档:

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

编辑:

连贯的不同结果背后的原因在于ConcurrentHashMap如何组织段并对它们进行迭代.

根据密钥的哈希值将密钥映射到不同的段:

"1" -> 15
"2" -> 0
"3" -> 6

"4" -> 5
"Samsung" -> 7

当调用迭代器时,它会迭代从最后到第一个的段.

因此,在0时刻,迭代器从段15开始,在那里找到键"1"="Windows phone",它首先进入输出.

然后,由于迭代器内部实现,它到达下一个元素,即段6的"3"="HTC".

此时插入"S5"就到位了.如果键是"4",它将进入第5段,如果键是"三星",它将进入第7段.

发送"HTC"到输出后,它搜索下一个元素.

当键为"4"时,它进入段5,找到"4"="S5",并将其发送到输出.

当键是"三星"时,该条目进入第7段,该段已被扫描并被迭代器发现为空,因此它找不到它并直接进入段0以检索"2"="Iphone".

这解释了这种行为.