modCount 的核心作用是检测并发修改,它定义在 AbstractList 中,Vector 和 Stack 的结构性操作均会更新它,Iterator 通过比对 modCount 与 expectedModCount 来触发 ConcurrentModificationException。

modCount 在 Vector 和 Stack 的继承关系中,核心作用是**检测并发修改**,直接影响 Iterator 的行为——一旦迭代过程中结构被修改(比如 push/pop),modCount 不匹配就会触发 ConcurrentModificationException。
modCount 的归属与初始化
它定义在 AbstractList 中(Vector 的祖父类),是受保护的 transient 成员变量:
protected transient int modCount = 0;Vector 每次结构性修改(如 addElement、removeElement)都会自增 modCount;Stack 的 push/pop 方法底层调用 Vector 的 addElement/removeElementAt,因此也自动更新 modCount。
Iterator 如何使用 modCount
Vector 提供的 Iterator(如 Itr 内部类)在创建时会把当前 modCount 快照保存为 expectedModCount。后续每次调用 next() 或 remove() 前,都会检查:
立即学习“Java免费学习笔记(深入)”;
- 当前 modCount 是否仍等于 expectedModCount
- 不等则抛出 ConcurrentModificationException
例如:用 for-each 遍历一个 Stack,循环中执行 pop() —— 这会触发 Vector 的 removeElementAt,导致 modCount +1,下一次 next() 就会失败。
Stack 的“伪栈”特性加剧风险
Stack 继承 Vector,除了 push/pop/peek,还能直接调用 elementAt、removeElement、insertElementAt 等 Vector 方法。这些操作同样改变 modCount,但容易被忽略:
- 遍历时调用 stack.get(i) 不影响 modCount(非结构性)
- 但调用 stack.removeElement(obj) 或 stack.clear() 会触发 modCount 变更
- 哪怕只用 Stack 接口方法,pop() 本质仍是 removeElementAt(size()-1),modCount 依然递增
为什么 Vector 的同步不能避免该异常
Vector 方法加了 synchronized,保证多线程下单个操作原子性,但 无法保证“迭代 + 修改”这一复合操作的原子性:
- Iterator.next() 是一个操作,pop() 是另一个操作
- 两者之间存在时间窗口,modCount 已变而 expectedModCount 未更新
- synchronized 锁的是 this 对象,但 Iterator 和修改方法各自持锁后释放,不构成串行化执行


















