1.快速失败(fail-fast)
      在用迭代器遍历一个集合对象,如果在遍历过程中集合内容发生了改变(也就是多线程时的数据不安全问题),则会抛出Concurrent Modification Exception(并发修改异常)。

快速失败与安全失败

在ArrayList的所有涉及结构变化的方法中都增加modCount的值,包括:add()、remove()等等,这些方法每调用一次,modCount的值就加1。这是在父类AbstractList中定义了一个int型的属性:modCount
AbstractList中的iterator()方法(ArrayList直接继承了这个方法)使用了一个私有内部成员类Itr,生成一个Itr对象(Iterator接口)返回:public Iterator iterator() { return new Itr(); }
Itr实现了Iterator()接口,其中也定义了一个int型的属性:expectedModCount,这个属性在Itr类初始化时被赋予ArrayList对象的modCount属性的值。

其中modCount值是实际被修改数,expectedModCount是遍历时的初始值(注意:是遍历时从modCount上获取的)

int expectedModCount = modCount;
上图中就是java.util下的ArrayList遍历集合时进行的数据检查,当调用next()方法时会执行此判断,如果两个值不相等,则会报出Concurrent Modification Exception(并发修改异常)。

快速失败与安全失败

解决方案:
2.fail-safe(安全失败)
将ArrayList替换成java.util.concurrent包下对应的类

遍历集合时是遍历拷贝的复印件而不是原件,所以也就不会触发checkForComodification()进行检查

不过之所以还是叫失败的原因,数据是安全的,它不会报出Concurrent Modification Exception(并发修改异常)。

不过它不会遍历最新的数据,也是拿着遍历是拷贝的复印件继续遍历,当在多线程时有其他线程增、删、改、了数据就

不能遍历到最新的数据了。

总结
快速失败是对遍历集合的一种检查机制,如果要求数据保持最新,避免遍历被修改后的数据,快速失败可以直接中断抛出异常。

安全失败就是对于数据实时性要求不高而采用的一种机制,不管在多线程时如何修改我遍历的都是复印件,并且不抛出异常。

相关文章: