https://www.cnblogs.com/zhangyinhua/p/7688722.html#_lab2_4_2
fail-fast和fail-safe区别
简单的来说:在java.util下的集合都是发生fail-fast,而在java.util.concurrent下的发生的都是fail-safe。
fail-fast
快速失败,例如在arrayList中使用迭代器遍历时,有另外的线程对arrayList的存储数组进行了改变,比如add、delete、等使之发生了结构上的改变,
所以Iterator就会快速报一个java.util.ConcurrentModificationException 异常(并发修改异常),这就是快速失败。
fail-safe
安全失败,在java.util.concurrent下的类,都是线程安全的类,他们在迭代的过程中,如果有线程进行结构的改变,不会报异常,而是正常遍历,这就是安全失败
但java.util.concurrent包下,对集合有结构的改变,却不会报异常?
在concurrent下的集合类增加元素的时候使用Arrays.copyOf()来拷贝副本,在副本上增加元素,如果有其他线程在此改变了集合的结构,那也是在副本上的改变,而不是影响到原集合;
迭代器还是照常遍历,遍历完之后,改变原引用指向副本,所以总的一句话就是如果在次包下的类进行增加删除,就会出现一个副本。所以能防止fail-fast,这种机制并不会出错,所以我们叫这种现象为fail-safe。
总结
fail-fast是否会发生,与线程安全与否,没有关系,与实现增删的底层机制有关;
是直接操作引用,还是操作副本
代码
fail-fast
public static void main(String[] args) {
ArrayList<Integer> list=new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Iterator<Integer> iterator=list.iterator();
while(iterator.hasNext()){
System.out.print(iterator.next());
list.add(4); //在遍历的时候add
}
}
------------------------------------------------------------
1Exception in thread "main" java.util.ConcurrentModificationException
fail-safe
public static void main(String[] args) {
CopyOnWriteArrayList<Integer> list=new CopyOnWriteArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Iterator<Integer> it1=list.iterator();
while(it1.hasNext()){
System.out.print(it1.next());
list.add(4);
}
System.out.println();
Iterator<Integer> it2=list.iterator();
while(it2.hasNext()){
System.out.print(it2.next());
}
}
------------------------------------------------------------
123
123444