并发修改异常不一致

时间:2016-05-13 06:25:56

标签: java loops

如果我取消注释行list.add(" 3"),则抛出ConcurrentModificationException。对于两个元素,它工作正常,并抛出1或3个元素异常?对此行为的任何解释?

import java.util.*;

public class ConException {

    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        list.add("1");
        list.add("2");
        //list.add("3");
        for(String x: list){
            list.remove("1");
        }
        System.out.println(list);
    }
}

2 个答案:

答案 0 :(得分:0)

您在迭代时无法更改列表 因此,您无法在list.remove("1")循环内拨打for (String x: list) 删除循环,只需删除“1”元素。

如果要删除所有“1”元素,可以通过以下方式执行此操作:

while (list.remove("1")) {}

修改
这是用于for循环的ArrayListIterator类的反编译代码。在每次迭代后调用next方法,可以抛出ConcurrentModificationException

private class ArrayListIterator implements Iterator<E> {
    /** Number of elements remaining in this iteration */
    private int remaining = size;

    /** Index of element that remove() would remove, or -1 if no such elt */
    private int removalIndex = -1;

    /** The expected modCount value */
    private int expectedModCount = modCount;

    public boolean hasNext() {
        return remaining != 0;
    }

    @SuppressWarnings("unchecked") public E next() {
        ArrayList<E> ourList = ArrayList.this;
        int rem = remaining;
        if (ourList.modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (rem == 0) {
            throw new NoSuchElementException();
        }
        remaining = rem - 1;
        return (E) ourList.array[removalIndex = ourList.size - rem];
    }

    public void remove() {
        Object[] a = array;
        int removalIdx = removalIndex;
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        if (removalIdx < 0) {
            throw new IllegalStateException();
        }
        System.arraycopy(a, removalIdx + 1, a, removalIdx, remaining);
        a[--size] = null;  // Prevent memory leak
        removalIndex = -1;
        expectedModCount = ++modCount;
    }
}

在以下情况下,我们会从next方法抛出异常:

if (ourList.modCount != expectedModCount) {
    throw new ConcurrentModificationException();
}

我们的modCount变量在remove次迭代时已更改,因此下一次next调用将失败。

答案 1 :(得分:0)

请阅读ConcurrentModificationException的java文档 https://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html

在您的情况下,只有在ArrayList中有2个元素时才会获得异常,在所有其他情况下,您会得到ConcurrentModificationException。

正如javaDoc声明的那样,它依赖于JRE确定是否正在进行任何并发修改,并且它不是保证确定相同的方法,正如javadoc中明确指出的那样。

  

请注意,通常情况下无法保证快速失败的行为   说话,在场的情况下不可能做出任何硬性保证   非同步并发修改