java - 并发 HashMap - 故障安全问题

标签 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");
}

输出是:

Windows Phone
HTC
iPhone

这是我理解的故障安全示例。

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

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");
}

输出是

Windows Phone
HTC
S5
iPhone

以上两个代码片段有什么区别。在第二个代码片段中,我添加了 cMap.put("4", "S5"); 并且它正在被添加。但是在第一个片段中,我添加了 cMap.put("Samsung", "S5");,它没有被添加到 ConcurrentHashmap。我是不是犯了什么错误,或者其他什么可能是造成这种不同输出的原因。

提前致谢。

最佳答案

与非并发 hashmap 不同的是,如果在迭代时添加内容,并发 map 不会快速失败。

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

来自文档:

Iterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration

编辑:

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

根据键的散列,键被映射到不同的段:

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

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

当一个迭代器被调用时,它从最后一个到第一个迭代段。

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

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

此时“S5”的插入就位了。如果 key 是“4”,它将转到第 5 段,如果 key 是“Samsung”,它将转到第 7 段。

在发送“HTC”输出后,它搜索下一个元素。

当key为“4”时,进入第5段,找到“4”="S5",送出输出。

当key为“Samsung”时,进入第7段,已经被迭代器扫描过,发现为空,所以没有找到,直接进入第0段取回“2”=“Iphone” .

这解释了行为。

关于java - 并发 HashMap - 故障安全问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25688963/

相关文章:

java - 为什么在实例(Java)上调用方法时不需要导入类

java - "java.lang.ClassFormatError: Invalid pc in LineNumberTable"的可能原因

java - Eclipse - 输出字符不同于键盘键值

java - 为什么我的 HashMap 有重复的键?

java - 如何在多线程应用程序中自动更新ConcurrentMap的值?

java - ConcurrentHashMap 中是否可以有超过 32 个锁

java - 用 Java 创建文本冒险

java - HashMap 中最有效的键对象类型?

hash - 如何从可哈希的库中创建一个不可哈希的、类 C 的枚举?

java - ConcurrentHashMap 的弱一致迭代器