DescendingIterator 同样遵循 fail-fast 机制,其 expectedModCount 初始化为 modCount,每次 next() 或 hasNext() 前调用 checkForComodification 检查 modCount 是否变化,不等则抛 ConcurrentModificationException;remove() 会同步更新 expectedModCount,但其他结构性修改(如 addFirst、removeLast 等)均触发异常。

LinkedList 的 DescendingIterator 同样遵循 fail-fast 机制,其底层 modCount 检查逻辑与正向迭代器(ListItr)一致,但实现细节需结合双向链表结构和逆序遍历特性来理解。
DescendingIterator 也维护 expectedModCount
LinkedList 内部的 DescendingIterator 是一个私有静态类,它实现了 Iterator<e></e> 接口。和 ListItr 一样,它在构造时会捕获当前的 modCount 值,并保存为自己的 expectedModCount 字段:
- 该字段在实例化时初始化:
expectedModCount = modCount -
modCount定义在AbstractSequentialList(LinkedList 的父类)中,是transient int类型,所有结构性修改(如addFirst、removeLast、clear、remove(Object)等)都会使其递增 - 每次调用
next()或hasNext()前,都会触发checkForComodification()方法
checkForComodification 的行为完全一致
DescendingIterator 复用了 LinkedList 中统一的校验逻辑:
监控一个或多个 GitCode 仓库的 PR,通过 OpenClaw Gateway 自动执行 AI 审查,发布 PR 评论,并发送钉钉和企业微信通知。
- 其
checkForComodification()方法与ListItr中的完全相同:直接比较modCount != expectedModCount - 一旦不等,立即抛出
ConcurrentModificationException,不区分是正向还是逆向遍历 - 注意:通过
DescendingIterator.remove()删除元素时,会同步更新expectedModCount = modCount,因此不会触发异常;但若用LinkedList.remove(...)或其他线程修改,则必然失败
逆序遍历不影响 fail-fast 的触发时机
尽管 DescendingIterator 从尾节点开始向前遍历(使用 last 指针和 prev 链接),但它的并发安全模型与方向无关:
立即学习“Java免费学习笔记(深入)”;
- modCount 是全局的修改计数器,不区分操作位置(头/尾/中间)或遍历方向
- 只要在迭代过程中发生任何结构性修改(包括
addFirst、addLast、removeFirst、removeLast、remove(Object)、clear等),modCount就会变化 - 下一次调用
next()时,校验失败即抛异常——哪怕刚遍历完最后一个元素,紧接着调用addFirst(),再调next()仍会失败
实际写法中容易忽略的点
开发者常误以为“只读遍历+尾部操作”就安全,但其实:
-
list.add("x")和list.addLast("x")都会触发modCount++ - 即使
DescendingIterator当前指向的是last节点,addFirst()仍会破坏一致性 - 多线程场景下,哪怕只是另一个线程调用
size()不会改modCount,但任何add/remove都会——fail-fast 只关心结构变更,不关心是否影响当前遍历路径

















