美文网首页
这段代码为什么会报错?

这段代码为什么会报错?

作者: 少寨主的互联网洞察 | 来源:发表于2019-01-29 14:57 被阅读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这个成员变量,就是为了辨别多线程修改集合时出现的错误。
    在单线程的环境下也可能会发生该异常

    相关文章

      网友评论

          本文标题:这段代码为什么会报错?

          本文链接:https://www.haomeiwen.com/subject/wqjxsqtx.html