商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Java中 fail-fast 快速失败机制在 ArrayList 遍历时的触发过程

Java中 fail-fast 快速失败机制在 ArrayList 遍历时的触发过程

  发布于2026-07-15 阅读(0)

扫一扫,手机访问

可能有些同学以为fail-fast只是并发场景下才会出现的问题,其实不然。它本质上就是modCountexpectedModCount不一致时,抛出的一个ConcurrentModificationException。单线程下,只要违规操作,照样会触发这个异常。核心就一句话:迭代器创建之后,集合被外部修改了。

触发的前提条件

说到底,触发这个异常需要同时满足三个条件——少了任何一个,都报不出来:

  • 必须使用迭代器(iterator())或增强for循环遍历ArrayList,因为增强for循环底层就是迭代器;
  • 遍历过程中,有代码对ArrayList执行了结构性修改——注意,这里说的结构性修改,是指add()remove()clear()这类会改变size的操作;
  • 这个修改不是通过当前迭代器自身的remove()add()(ListIterator才有add)方法完成的。

内部计数器是怎么工作的

ArrayList继承自AbstractList,里面定义了一个关键字段——protected transient int modCount = 0。每次结构性修改,modCount都会加1。而当你创建一个迭代器(比如ArrayList.Itr)时,它会在构造瞬间把当前的modCount复制一份,存为自己的expectedModCount

之后每次调用next(),都会先执行checkForComodification(),检查这两个值是否相等。一旦发现modCount != expectedModCount,一句废话没有,直接抛出ConcurrentModificationException

Ja va中 fail-fast 快速失败机制在 ArrayList 遍历时的触发过程

常见触发场景举例

下面这些写法,随便挑一个,都会触发异常:

  • 增强for循环里直接调用list.remove(x)——注意,不是迭代器的remove;
  • while + iterator遍历过程中,用list.add(y)插入新元素;
  • 多线程环境下,线程A用iterator遍历,线程B同时调用list.remove()
  • 单线程也有坑:先获取iterator,再调用list.clear(),之后再调用next(),照样翻车。

很多新手会想当然地以为“单线程就没问题”,结果踩了坑才反应过来。

为什么for-i循环有时不报错?

普通for循环——就是for(int i=0; i这种写法——它不依赖迭代器,也不检查modCount,所以不会触发fail-fast机制。但千万别以为这就安全了。它不会自动跳过已删除的位置,搞不好就会抛出IndexOutOfBoundsException,或者跳过元素导致数据错乱。这属于隐性风险,不是安全替代方案,只是换了一种翻车的方式而已。

本文转载于:https://www.php.cn/faq/2823569.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。