在前几个回合中,我们已经详细了解过了 Java 集合中的List、Set 和 Map,对这部分内容感兴趣的朋友可以关注我的公众号「Java面典」了解。今天我们将为各位介绍集合的失败机制——fail-fast与fail-safe。
fail-fast(快速失败)
现象
在用迭代器遍历集合对象的时候,如果此时对集合对象进行了增加、删除、修改操作的时候,会抛出Concurrent Modification Exception。
原理
- modCount :表示集合的修改次数,包括了调用集合本身修改方法(如 add、remove)进行的修改和调用集合迭代器修改方法进行的修改;
- expectedmodCount:表示迭代器对集合进行修改的次数;
- 当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测 modCount 是否与 expectedmodCount 相等,是的话就返回遍历;否则抛出异常,终止遍历。
说明
java.util 包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)。
场景
以下两种场景会导致 fail-fast:
- 单线程环境:在遍历过程中,修改了集合,会发生 fail-fast 异常;
- 多线程环境:一个线程正在遍历集合的时候,另一个线程对集合进行了修改,会导致遍历线程发生 fail-fast。
fail-safe(安全失败)
现象
采用安全失败机制的集合容器,在遍历时不是直接在原集合遍历的,而是先复制原有集合内容,在拷贝的集合上进行遍历。
原理
由于遍历是在拷贝集合上进行的,而修改是在原集合上执行的。所以对原集合的修改,并不会导致异常的发生。
说明
java.util.concurrent 包下的容器都是安全失败,可以在多线程下并发使用,并发修改。
存在的问题
fail-safe 虽然不会抛出 ConcurrentModificationException 异常,但是也存在其问题:
- 因为需要复制集合对象,导致内存开销大;
- 因为循环是在复制集合上进行的,所以无法保证数据的一致性。
Java集合系列推荐
Java集合03——你不得不了解的Map
Java集合02——三分钟了解你必须掌握的两个Set
Java集合01——List 的几个实现类,了解一下?
网友评论