Fail-Fast 和 Fail-Safe 机制

100 阅读2分钟

Fail-Fast 机制

快速失败机制,该机制用于判断集合在使用 Iterator 迭代器遍历是否发生了增删全清除等改变长度的操作,如果发生则主动抛出 ConcurrentModificationException 异常中断遍历,避免后续出现问题。

java.util 包下的集合类都是快速失败的。

Fail-Fast 原理:

Iterator 内部维护了两个变量,一个 modCount 和一个 expectedModCount,一开始两者默认都等于0,当发生增删全清楚等改变长度的操作时,modCount 会加一。而每一次循环之前会校验两个变量是否相等只要不等就会立刻抛出异常

解决方法也很多,比如不用迭代器用 for 循环、增删后立刻 break 停止循环、使用 Iterator 的删除方法(没有增加方法)、使用 JDK 8的 Stream 流。

Fail-Safe 机制

安全失败机制,和 Fail-Fast 相反,Fail-Safe 允许在迭代器遍历过程中修改元素

java.util.concurrent 包下的容器都是安全失败的,可以在多线程下并发修改。常见的的使用 fail-safe 方式遍历的容器有 ConcerrentHashMap 和 CopyOnWriteArrayList 等。

Fail-Safe 原理:

采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容在拷贝的集合上进行遍历。但迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的

Fail-Safe 和写时复制类似,不过写时复制只有在进行写操作时才会复制一份副本,然后在副本上进行写操作。而 Fail-Safe 是一开始就复制集合内容,在复制的副本上进行遍历。