什么是fail fast和fail safe?

在 Java 中,fail-fast(快速失败)和 fail-safe(安全失败)是两种在集合类进行遍历或修改时的异常处理机制。它们核心区别在于:是否允许在遍历过程中结构被修改,以及是否会抛出 ConcurrentModificationException


✅ 一、fail-fast(快速失败)

📌 定义:

当集合在被遍历期间结构发生变化(非当前迭代器自身的 remove),则会立即抛出 ConcurrentModificationException 异常

🧠 原理:

fail-fast 机制通过一个modCount 结构修改计数器来实现。

  • 每当集合结构发生变化(add/remove),modCount++

  • 迭代器创建时,会记录一个期望值 expectedModCount = modCount

  • 遍历过程中,每次 next()/hasNext() 都会检查:

    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
    

❗适用于哪些集合?

  • ArrayList, HashMap, HashSet, LinkedList 等大多数 JDK 中的常规集合类

❌ 问题场景:

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");

for (String s : list) {
    list.remove(s); // 会抛 ConcurrentModificationException
}

✅ 二、fail-safe(安全失败)

📌 定义:

遍历期间即使集合发生结构变化,也不会抛异常,能够容忍并发修改,但修改对当前迭代器不可见(即“弱一致性”)。

🧠 原理:

fail-safe 迭代器不直接在原始集合上操作,而是复制一份快照(CopyOnWrite)或者使用弱一致的底层数据结构(如跳表)

✅ 常见实现:

实现类机制特性
CopyOnWriteArrayList写时复制遍历时快照,线程安全,适合读多写少
ConcurrentHashMap分段锁 / CAS + bin 锁支持并发修改,遍历弱一致
ConcurrentSkipListMap跳表结构排序、并发安全

✅ 示例:

CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
list.add("a");
list.add("b");

for (String s : list) {
    list.remove(s);  // 不会抛异常,安全失败
}

✅ 三、对比总结

特性Fail-FastFail-Safe
迭代结构变化响应抛出 ConcurrentModificationException不抛异常,允许修改
线程安全❌ 否(多数为非线程安全集合)✅ 是(基于 CopyOnWrite 或 CAS)
实现方式检查 modCount快照副本或弱一致性容器
修改是否可见❌ 修改直接失败❌ 修改对当前迭代器不可见(快照)或延迟可见
性能影响遍历性能好,但不容错写性能差(CopyOnWrite),适合读多写少

✅ 四、使用建议

场景建议容器 / 机制
高并发读写ConcurrentHashMap
多线程读多写少,且遍历频繁CopyOnWriteArrayList
单线程或内部控制修改普通集合 + fail-fast 机制
避免 fail-fast 异常使用显式 Iterator.remove()

是否需要我再补充 CopyOnWriteArrayListConcurrentHashMap 的 fail-safe 原理源码细节?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值