For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries. Similarly, Iterators, Spliterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time.
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html
经 V 友提醒,去看了下 javadoc ,然后发现了这句描述,于是决定复现:
public class Main {
private static ConcurrentHashMap<String,String> concurrentHashMap = new ConcurrentHashMap<>();
public static void main(String[] args) {
for(int i = 0 ; i < 100000 ; i++){
concurrentHashMap.put("Key"+i,"Value"+i);
}
new Thread(new Runnable() {
@Override
public void run() {
for (Map.Entry<String, String> entry : concurrentHashMap.entrySet()){
System.out.println("1key:"+entry.getKey()+",value:"+entry.getValue());
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (Map.Entry<String, String> entry : concurrentHashMap.entrySet()){
System.out.println("2key:"+entry.getKey()+",value:"+entry.getValue());
}
}
}).start();
new Thread(new Runnable() {
结果还是没有任何问题。然后我还有用线程在这个多线程遍历的同时去给其增加删除元素,量级也是 10 万,因为客户手机文件也差不多这个数量,结果还是没问题。
所以我想问一下,有办法复现吗?
1
DonaldY 2022-10-15 17:04:52 +08:00
ConcurrentHashMap 不会出现 ConcurrentModificationException 。
代码里都没有抛这个异常。 next 指针用 volatile 修饰的,可见。 |
2
LeegoYih 2022-10-15 17:35:13 +08:00
HashMap 修改数据时会修改 modCount 的值,遍历时发现 modCount 不一致说明存在另一个线程在修改数据,所以会抛出 ConcurrentModificationException
ConcurrentHashMap 文档上写了 They do not throw ConcurrentModificationException. 这也是符合预期的,如果别人一直在修改数据,我这边遍历一直报错,还让不让人看数据了。 后面 However 只是解释了 iterators 设计之初是为了单个线程遍历的,所以对 ConcurrentHashMap 遍历、size, isEmpty 和 containsValue 等操作只试用于监控或估计的目的,不能用来当做流程控制 /程序控制 |
3
Jooooooooo 2022-10-15 17:43:05 +08:00
They do not throw ConcurrentModificationException.
这不是 do not 吗? 你咋复现. |