首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >快速失败(fail-fast)和安全失败(fail-safe)

快速失败(fail-fast)和安全失败(fail-safe)

原创
作者头像
Eulogy
发布2025-07-10 01:07:25
发布2025-07-10 01:07:25
1130
举报
文章被收录于专栏:笔记本笔记本

快速失败(fail-fast)和安全失败(fail-safe)

java.util包下的容器都是快速失败的,java.concurrent包下的容器都是安全失败的。

fail-fast

在使用迭代器遍历一个容器时。如果在遍历的过程中,这个容器被增删改了,那么这个遍历就会立刻终止并且抛出一个Concurrent Modification Exception异常。

代码语言:java
复制
class 容器{
	int modCount;
	...
	
	public Iterator<E> iterator() {
        return new Itr();
    }
    
	private class Itr implements Iterator<E>{
		...
		int expectedModCount = modCount;
		
	}
}

看上面的代码,我们知道Iterator迭代器是容器类的一个内部类,我们创建迭代器的时候,迭代器会记录当前容器的修改的次数modCount。然后我们使用迭代器的hasNext()和next()方法去遍历的时候如果出现expectedModeCount和modCount不一致的情况,就会立马抛出异常,让上一层捕获,不再遍历。

这就是快速失败;“快速”指的是有修改则立马停止遍历,“失败”指的是遍历出错。

fail-safe

在迭代器遍历容器的时候,如果在遍历的过程中,集合被修改了,那么集合并不会抛出异常,不会崩溃而是会继续执行完遍历。“安全”在程序会接着运行,不会崩溃,“失败”在遍历的容器出错了,读不到新修改的元素,是数据一致性失败。

以CopyOnWriteArrayList为例,它的读写是不同的机制,读的时候不会有任何限制,所有线程都可以同时进行读。而写的时候会通过锁阻塞别的写操作,与其他地方不同的是,这里读和写不是互斥的,只有写和写是互斥的。写的时候会先获取锁,保证只有一个线程在写,然后再copy一份原来的容器,再在这个新的容器副本上写,写好之后再让原来容器的指针指向这个新的副本。所以在写的时候,读线程完全不受影响,它可以安全地读完容器元素,只是读的可能不是最新元素而已。

总结

Fail-Fast 是指在遍历集合过程中如果检测到集合被结构性修改,立即抛出 ConcurrentModificationException 异常,保证数据一致性但不容忍并发修改;而 Fail-Safe 则采用读写分离或弱一致性策略,即使集合在遍历时被修改,也不会抛出异常,程序可以继续运行,但读取的数据可能不是最新的。前者注重一致性与快速错误发现,适用于单线程或低并发环境;后者注重容错性与线程安全,适用于读多写少的高并发场景。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 快速失败(fail-fast)和安全失败(fail-safe)
    • fail-fast
    • fail-safe
    • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档