Java中 fail-fast 机制在 AbstractList 内 checkForComodification 的执行时机

作者:袖梨 2026-07-14
checkForComodification在每次调用next()、remove()、previous()、set()或add()时触发,因这些操作均在方法入口处前置校验modCount与expectedModCount是否一致,确保迭代过程中的结构一致性。

checkForComodification 方法在 AbstractList 的迭代器中,**每次调用 next()remove()previous()set()add() 时都会执行。

哪些方法会触发 checkForComodification?

该检查不是仅在遍历开始或结束时发生,而是嵌入在迭代器核心操作的入口处。以 ArrayList.Itr(继承自 AbstractList.Itr)为例:

  • next():在取下一个元素前立即校验
  • remove():在删除上一个返回的元素前校验(注意:这是迭代器自身的 remove,非集合的 remove
  • previous()next()ListIterator 中同样前置校验
  • set()add()(仅 ListIterator 支持)也严格校验

为什么是“每次”而不是“仅首次”?

因为结构性修改可能发生在任意迭代步骤之间。比如线程 A 遍历到第 3 个元素后暂停,线程 B 此时调用 list.add()modCount 变更 → 线程 A 继续调用 next() 时立刻发现不一致。延迟检查会导致状态错乱或跳过/重复元素,而即时校验能确保每次操作都基于“当前视图一致性”。

有没有不触发 checkForComodification 的情况?

有。以下操作不会触发该检查:

立即学习“Java免费学习笔记(深入)”;

  • 仅读取元素(如 get(int)),不涉及迭代器
  • 使用 Enumeration(如 Vector.elements()),它不是 fail-fast 的
  • 迭代器自身合法的结构修改:调用 iterator.remove() 会同步更新 expectedModCount,因此后续 next() 不会报错

关键细节:校验发生在“操作前”还是“操作后”?

标准实现(如 ArrayList.Itr.next())是先校验,再执行业务逻辑。部分 JDK 版本还在 finally 块中再次校验(防止操作中途被中断导致状态不一致),但主校验点始终在方法入口。这种设计保证了“失败即刻可见”,符合 fail-fast 的本质——不掩盖问题,不延迟暴露。

相关文章

精彩推荐