集合的快速失败机制

Java集合的快速失败机制 “fail-fast”?

答:

是java集合的一种错误检测机制,当多个线程对集合进行结构上的改变的操作时,有可能会产生 fail-fast 机制。

例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制。

原因:迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量。集合在被遍历期间如果内容发生变化,就会改变modCount的值(无论是add()、remove(),还是clear(),只要涉及到修改集合中的元素个数时,都会改变modCount的值)。每当迭代器使用hashNext()/next()遍历下一个元素之前,都会检测modCount变量是否为expectedmodCount值,是的话就返回遍历;否则抛出异常,终止遍历。

解决办法:

  1. 在遍历过程中,所有涉及到改变modCount值得地方全部加上synchronized。

  2. 使用CopyOnWriteArrayList来替换ArrayList
    3.如果使用vector替换arraylist,仍会报currentModificationException
    Vector源码可以发现它的很多方法都加上了synchronized来进行线程同步,例如add()、remove()、set()、get(),但是Vector内部的synchronized方法无法控制到遍历操作,所以即使是线程安全的Vector也无法做到线程安全地遍历。

如果想要线程安全地遍历Vector,需要我们去手动在遍历时给Vector加上synchronized锁,

并发容器支持并发的遍历和并发的更新。

主要的类有ConcurrentHashMap, CopyOnWriteArrayList 和CopyOnWriteArraySet

public class DelArrayList {
    

    public static List list=new ArrayList<>();
    public DelArrayList(){
        for(int i=0;i<6;i++){
            list.add(i);
            
        }
    }

    /**
     * @param args
     *            

* Description: *

*/ private static class ThreadA extends Thread{ public void run(){ Iterator it=list.iterator(); while(it.hasNext()){ System.out.println(it.next()); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } private static class ThreadB implements Runnable{ /* (non-Javadoc) * @see java.lang.Runnable#run() */ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } list.remove(2); } }
image.png

你可能感兴趣的:(集合的快速失败机制)