Java集合迭代器快速失败机制检测结构性修改(如add/remove),通过modCount与expectedModCount比对实现:创建迭代器时复制modCount值,每次next()前校验二者是否相等,不等则抛ConcurrentModificationException;该机制单线程下也会触发,本质是约束操作入口一致性,而非保障线程安全。

面试中讲清楚集合迭代失效机制,关键不是堆砌术语,而是用“计数器比对”这个核心逻辑串起行为、原因和边界。重点说清三点:它检测什么、怎么检测、为什么这样设计。
它检测的是结构性修改,不是所有修改
结构性修改指改变集合大小或内部结构的操作,比如 add()、remove()、clear()、addAll()。像 ArrayList 的 set(int index, E e) 这种只替换值、不增删元素的操作,不会触发 modCount 自增,也就不会导致快速失败。这点常被忽略,但能体现你读过源码。
底层靠两个整数的实时比对
每个支持 Fail-Fast 的集合(如 ArrayList、HashMap)内部都有一个 modCount 字段,记录结构性修改次数。创建迭代器时,会把当时的 modCount 值复制给迭代器自己的 expectedModCount。之后每次调用 next() 或 hasNext() 前,都会执行一次校验:
- 如果 modCount == expectedModCount,继续遍历
- 如果不等,立刻抛 ConcurrentModificationException
这个检查逻辑在 AbstractList$Itr 类里是公开方法 checkForComodification(),几行代码就能说明白。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
立即学习“Java免费学习笔记(深入)”;
单线程下也会失败,这不是线程安全机制
很多人误以为这是多线程专属问题。其实只要在遍历中用集合自身的方法(如 list.remove())改了结构,modCount 就会变,而迭代器里的 expectedModCount 没同步更新——下次 next() 一校验就崩。反过来说,用迭代器自己的 remove() 方法删除,它内部会同步更新 expectedModCount = modCount,就不会异常。这说明机制本质是约束操作入口的一致性,而非解决并发竞争。
Fail-Fast 不是保险丝,而是调试哨兵
官方文档明确指出:它属于 best-effort 检测,不能作为程序正确性的保障。比如在多线程极端时序下可能漏检;它的真正价值是帮你第一时间发现“边遍历边乱改”的逻辑错误。所以回答结尾可以加一句:“它不防并发,但能防手滑。”

















