1. 引言

本文将深入探讨Java中两种重要的迭代器机制:Fail-Fast迭代器Fail-Safe迭代器

  • Fail-Fast系统:一旦检测到异常立即中止操作,快速暴露问题并终止整个流程
  • Fail-Safe系统:遇到异常时不会中止操作,尽可能避免抛出异常

这两种机制在并发场景下的表现差异显著,理解它们的区别对编写健壮的并发代码至关重要。

2. Fail-Fast迭代器

Java中的Fail-Fast迭代器在底层集合被修改时会立即"罢工"。

工作原理

集合内部维护一个计数器modCount

  • 每次添加/删除元素时,modCount递增
  • 迭代时每次调用next()都会比较当前modCount与初始值
  • 不匹配时抛出ConcurrentModificationException,终止整个操作

典型代表java.util包下的集合(如ArrayListHashMap等)的默认迭代器

ArrayList<Integer> numbers = // ...

Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {
    Integer number = iterator.next();
    numbers.add(50); // 触发ConcurrentModificationException
}

⚠️ 重要特性

  1. 非绝对保证:并发修改时行为不可预测,仅尽力抛出异常
  2. 安全删除:使用迭代器的remove()方法删除元素是安全的
  3. 危险操作:直接调用集合的remove()方法会触发异常
ArrayList<Integer> numbers = // ...

// 安全操作示例
Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {
    if (iterator.next() == 30) {
        iterator.remove(); // ✅ 安全
    }
}

// 危险操作示例
iterator = numbers.iterator();
while (iterator.hasNext()) {
    if (iterator.next() == 40) {
        numbers.remove(2); // ❌ 抛出ConcurrentModificationException
    }
}

3. Fail-Safe迭代器

Fail-Safe迭代器优先保证操作不中断,避免异常处理带来的麻烦。

工作机制

  • 创建集合的克隆副本进行迭代
  • 原集合修改不影响迭代副本
  • 即使集合被修改,迭代仍继续执行

⚠️ 术语澄清:严格来说不存在真正的"Fail-Safe",更准确的术语是弱一致性(Weakly Consistent)

典型代表java.util.concurrent包下的集合(如ConcurrentHashMapCopyOnWriteArrayList等)

ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

map.put("First", 10);
map.put("Second", 20);
map.put("Third", 30);
map.put("Fourth", 40);

Iterator<String> iterator = map.keySet().iterator();

while (iterator.hasNext()) {
    String key = iterator.next();
    map.put("Fifth", 50); // ✅ 不会抛出异常
}

关键特性

  1. 数据一致性:迭代器可能反映也可能不反映集合的修改(取决于具体实现)
  2. 性能开销:创建集合副本带来额外的时间和内存消耗
  3. 数据滞后:迭代的是副本而非原集合,可能无法获取最新数据

📌 ConcurrentHashMap的特殊行为

// 上述代码中迭代会执行5次
// 因为ConcurrentHashMap的迭代器是弱一致的
// 可能(但不保证)反映迭代器创建后的修改

4. 总结

通过本文我们深入理解了两种迭代器机制的核心差异:

特性 Fail-Fast迭代器 Fail-Safe迭代器
异常处理 立即抛出ConcurrentModificationException 不抛出异常
数据一致性 强一致性 弱一致性
性能开销 高(需创建副本)
典型实现 ArrayList, HashMap ConcurrentHashMap等并发集合
适用场景 单线程或严格同步环境 高并发修改场景

💡 开发建议

  • 单线程环境优先使用Fail-Fast迭代器(性能更好)
  • 高并发修改场景选择Fail-Safe迭代器(避免异常中断)
  • 谨慎处理迭代过程中的集合修改,优先使用迭代器提供的修改方法

掌握这两种迭代器的行为差异,能帮助我们在并发编程中避免常见陷阱,编写更健壮的代码。


原始标题:Fail-Safe Iterator vs Fail-Fast Iterator | Baeldung