定义
fail-fast是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能(不是一定)会产生fail-fast机制。
在非java.util.concurrent包下的类,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。
原理
产生fail-fast,是通过抛出ConcurrentModificationException异常来触发的。
在集合类型中,均有一个记录该集合结构改变的modCount变量,当结构发生改变(增、删、改、清空)时,该值 modCount++;记录;
如:ArrayList中的:
在HashMap中:
在获取集合中元素,或者增、删操作时,都会检查modCount != expectedModCount,如果为true,则modCount在结构发生变化被修改掉了,此时抛出ConcurrentModificationException。
解决办法(fail-safe机制)
使用java.util.concurrent包中CopyOnWriteArrayList来替换ArrayList。
CopyOnWriteArrayList所有可变操作(add、set 等等)都是通过对底层数组进行一次新的复制来实现的。
fail-safe机制有两个问题
(1)需要复制集合,产生大量的无效对象,开销大
(2)无法保证读取的数据是目前原始数据结构中的数据。
该类产生的开销比较大,但是在两种情况下,它非常适合使用。1:在不能或不想进行同步遍历,但又需要从并发线程中排除冲突时。2:当遍历操作的数量大大超过可变操作的数量时。
CopyOnWriterArrayList根本就不会产生ConcurrentModificationException异常,也就是它使用迭代器完全不会产生fail-fast机制。