SynchronizedMap抛出ConcurrentModificationException的疑问及偶现原因
关于SynchronizedMap抛出ConcurrentModificationException的问题解答
你的理解是否正确?
不完全准确哦——这个异常并不是get方法访问导致的,核心原因出在迭代操作上:
Collections.synchronizedMap会给单个的put、get方法加上同步锁,保证单个方法的线程安全;- 但它的迭代器是「快速失败(fail-fast)」设计,而且整个遍历过程没有被同步保护。
你的main线程在执行for (Map.Entry<String, Integer> e : syncMap.entrySet())时,本质是通过迭代器遍历map;与此同时,MapHelper1/2/3线程正在调用put修改map的结构。当迭代器检测到遍历期间map被其他线程修改,就会抛出ConcurrentModificationException。
为什么有时不会抛出异常?
这是线程调度的随机性导致的:
- 如果main线程的遍历操作刚好在三个helper线程执行
put之前就完成了,迭代器不会检测到任何结构变化,自然不会抛异常; - 只有当helper线程的
put操作恰好发生在main线程遍历的过程中时,异常才会触发。
线程的执行顺序由JVM和操作系统调度决定,没有固定规律,所以会出现时有时无的现象。
如何解决这个问题?
你需要在遍历的时候手动给syncMap加锁,确保遍历过程中其他线程无法修改map:
synchronized (syncMap) { for (Map.Entry<String, Integer> e : syncMap.entrySet()) { System.out.println(e.getKey() + "=" + e.getValue()); } }
内容的提问来源于stack exchange,提问作者ghostrider
相关产品推荐
相关产品推荐

