这段代码为什么会报错?

2019-01-29  本文已影响0人  少寨主的互联网洞察

我们先来看一段简单的代码:

public class VectorFor {
    public static void test1(Vector<Integer> vector){
        for (Integer i: vector) {
            if(i.equals(3)){
                vector.remove(i);
            }
        }
    }
    public static void main(String[] args) {
        Vector<Integer> vector=new Vector();
        vector.add(1);
        vector.add(2);
        vector.add(3);
        test1(vector);
    }
}

看上去没什么不妥,就是遍历删除指定元素嘛,运行呢?

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.Vector$Itr.checkForComodification(Vector.java:1184)
    at java.util.Vector$Itr.next(Vector.java:1137)
    at com.example.demo.plaintest.VectorFor.test1(VectorFor.java:7)
    at com.example.demo.plaintest.VectorFor.main(VectorFor.java:18)

Process finished with exit code 1

抛出了一个ConcurrentModificationException异常
哪里抛出来的呢?

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

哪里调的这个方法呢?

public E next() {
            synchronized (Vector.this) {
                checkForComodification();
                int i = cursor;
                if (i >= elementCount)
                    throw new NoSuchElementException();
                cursor = i + 1;
                return elementData(lastRet = i);
            }
        }

那么表面原因很简单,就是modCount != expectedModCount,这里foreach循环其实还是用的迭代器,我这里调用的remove方法,这个方法里肯定有修改modcount的地方,去看看

public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }

一直追踪下去都没有看见更新expectedModCount的操作,所以呢到后面check的时候就指定会报错了


那么为什么会有它呢?参考了一下别的文章给出了解释
这个和多线程并发修改相关,先介绍一下fail-fast机制:

“快速失败”也就是fail-fast,它是Java集合的一种错误检测机制。当多个线程对集合进行结构上的改变的操作时,有可能会产生fail-fast机制。记住是有可能,而不是一定。例如:假设存在两个线程(线程1、线程2),线程1通过Iterator在遍历集合A中的元素,在某个时候线程2修改了集合A的结构(是结构上面的修改,而不是简单的修改集合元素的内容),那么这个时候程序就会抛出 ConcurrentModificationException 异常,从而产生fail-fast机制。

之所以有modCount这个成员变量,就是为了辨别多线程修改集合时出现的错误。
在单线程的环境下也可能会发生该异常

上一篇下一篇

猜你喜欢

热点阅读