Vector的迭代器默认fail-fast,通过modCount检测结构修改并抛出ConcurrentModificationException;Enumeration不触发fail-fast,但结果不可靠;fail-fast是调试机制而非并发控制,避免异常应使用迭代器remove()或CopyOnWriteArrayList。

会触发 fail-fast 异常。
Vector 的迭代器默认是 fail-fast 的
Vector 提供的 iterator() 和 listIterator() 方法返回的迭代器,都基于内部的 modCount 机制实现 fail-fast。每次调用 next() 或 hasNext() 前,迭代器都会检查当前集合的修改次数(modCount)是否与创建时记录的一致。一旦发现不一致——比如在遍历中途被其他线程或同一线程的非迭代器方法(如 add()、remove()、clear())修改了结构,就立即抛出 ConcurrentModificationException。
- 这个行为与 ArrayList 完全一致,和 Vector 是否线程安全无关
- 注意:Vector 的线程安全性体现在每个 public 方法(如
add、get)都加了synchronized,但 fail-fast 是独立于同步机制的检测逻辑 - 也就是说,即使单线程下,用
iterator遍历时调用vector.remove(obj),也会触发异常
例外:Enumeration 不触发 fail-fast
Vector 还提供了一个传统接口 elements(),它返回的是 Enumeration 实例。这个枚举器不是 fail-fast 的,它不会检查 modCount,因此遍历时即使集合被修改,也不会抛异常——但结果可能不一致或遗漏元素,属于“尽力而为”的遍历。
- 这是 Vector 兼容早期 Java(JDK 1.0)遗留设计的结果
- 现代代码中应避免依赖
elements()做关键逻辑,因其行为不可靠
为什么线程安全类仍要 fail-fast?
fail-fast 不是为了替代同步,而是为了及早暴露逻辑错误。例如:
立即学习“Java免费学习笔记(深入)”;
- 开发者误以为“线程安全 = 可以边遍历边修改”,结果导致数据跳过或重复
- 单线程中因循环逻辑缺陷(如在 for-each 中 remove 元素)引发隐蔽 bug
- 它是一种调试辅助机制,不是并发控制方案
如何避免 fail-fast 异常
如果确实需要边遍历边修改,正确做法是:
- 使用迭代器自身的
remove()方法(安全,会同步更新expectedModCount) - 改用
java.util.concurrent包下的线程安全集合(如CopyOnWriteArrayList),其迭代器是 fail-safe 的 - 先收集待删/待改元素,遍历结束后统一操作(如用
removeAll()) - 对 Vector 加显式锁(不推荐,违背设计初衷且易死锁)


















