如何解析fail-fast与fail-safe迭代器在处理集合并发修改时的底层原理差异?
- 内容介绍
- 文章标签
- 相关推荐
本文共计699个文字,预计阅读时间需要3分钟。
区分fail-fast与fail-safe:
前者靠 modCount 和 expectedModCount 的比对触发 ConcurrentModificationException;后者如 CopyOnWriteArrayList 的迭代器,一创建就复制当前数组引用,后续所有 next() 都在副本上走,原集合增删改完全不影响迭代过程。
单线程下也会触发 ConcurrentModificationException?
会,而且很常见。这不是多线程专属问题,而是结构修改与迭代器生命周期冲突的必然结果。
- 用
for-each遍历ArrayList时调用list.remove(x)→ 触发异常 - 在
Iterator.hasNext()和next()之间,另一个方法修改了集合 → 触发异常 -
HashMap的entrySet().iterator()遍历时,外部调用put()或remove()→ 触发异常
关键点:只要不是通过迭代器自身的 remove() 方法修改,就可能踩中 modCount 不一致的检查点。
本文共计699个文字,预计阅读时间需要3分钟。
区分fail-fast与fail-safe:
前者靠 modCount 和 expectedModCount 的比对触发 ConcurrentModificationException;后者如 CopyOnWriteArrayList 的迭代器,一创建就复制当前数组引用,后续所有 next() 都在副本上走,原集合增删改完全不影响迭代过程。
单线程下也会触发 ConcurrentModificationException?
会,而且很常见。这不是多线程专属问题,而是结构修改与迭代器生命周期冲突的必然结果。
- 用
for-each遍历ArrayList时调用list.remove(x)→ 触发异常 - 在
Iterator.hasNext()和next()之间,另一个方法修改了集合 → 触发异常 -
HashMap的entrySet().iterator()遍历时,外部调用put()或remove()→ 触发异常
关键点:只要不是通过迭代器自身的 remove() 方法修改,就可能踩中 modCount 不一致的检查点。

