为什么我不能在更新集合元素期间获得并发修改异常?

时间:2018-03-18 13:32:53

标签: java concurrentmodification

我刚刚读到如果发生并发修改异常 我们在调用迭代器方法

之后添加,删除或更新集合

我理解为什么添加和删除集合元素会导致并发修改异常,但为什么更新会导致并发修改? 毕竟,在更新元素时​​,我们不会在结构上改变任何东西。

例如下面的代码来自arraylist实现

public E set(int index, E element) {
    rangeCheck(index);

    E oldValue = elementData(index);
    elementData[index] = element;
    return oldValue;
}

我们不更新实际用于检查并发修改的变量“modcount”。

我也试过我的自定义代码:

public static void main(String[] args) {
    ArrayList l= new ArrayList();
    l.add("string");
    l.add(3);
    Iterator it=l.iterator();
    Object o=it.next();
    l.set(0, "element");
    l.remove(o);
    //l.add(7);
    //it.next();

    System.out.println(it.next());
    System.out.println(l.get(0));
    int i;
    System.out.println(j+" "+j);
}

这也不会引发并发修改异常。

我可以知道为什么吗?

1 个答案:

答案 0 :(得分:4)

  

为什么更新应该导致并发修改?

如果通过“更新”表示调用set方法,则不会导致并发修改。 设置List中元素的值不是结构修改,因此在迭代期间执行时不会导致ConcurrentModificationException

来自ArrayList Javadoc的引言:

  

结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作; 仅设置元素的值不是结构修改   ...

     

此类的迭代器和listIterator方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时候对列表进行结构修改,除非通过迭代器自己的删除或添加方法,迭代器将抛出ConcurrentModificationException 。因此,面对并发修改,迭代器会快速而干净地失败,而不是在未来不确定的时间冒着任意的,非确定性行为的风险。