快速失败(fail-fast)和安全失败(fail-safe)了解吗?

快速失败(fail-fast)和安全失败(fail-safe)了解吗?
快速失败(fail-fast):快速失败是Java集合框架的一种错误检测机制。
- 当使用迭代器遍历集合对象时,如果在遍历过程中,其他线程对集合对象的内容进行了修改(增加、删除、修改),就会抛出
ConcurrentModificationException异常。
- 原理:迭代器在遍历时直接访问集合的内容,并且使用一个
modCount
变量来记录集合被修改的次数。在每次迭代器调用hasNext()
或next()
方法之前,都会检查modCount
的值是否与期望值相等,如果不相等,就抛出异常终止遍历。 - 注意:异常抛出的条件是
modCount != expectedModCount
。如果集合在修改后将modCount
恰好又设置为了期望值,那么异常就不会被抛出。因此,不能依赖于此异常来进行并发操作的编程,这个异常只是用于检测并发修改的bug。 - 场景:Java.util包中的集合类都是快速失败的,在多线程环境下进行并发修改(在迭代过程中修改)是不安全的,比如ArrayList类。
安全失败(fail-safe):
- 采用安全失败机制的集合容器在遍历时不直接访问集合的内容,而是先复制原有集合的内容,然后在复制的集合上进行遍历。
- 原理:由于迭代器遍历的是集合的拷贝,所以在遍历过程中对原集合的修改不会被迭代器检测到,因此不会触发ConcurrentModificationException异常。
- 缺点:基于拷贝内容的优点是避免了ConcurrentModificationException异常,但迭代器无法访问修改后的内容。即,在遍历期间,原集合发生的修改对迭代器是不可见的。
- 场景:Java.util.concurrent包下的容器类都是安全失败的,可以在多线程环境下并发使用和修改,例如CopyOnWriteArrayList类。