使用复制构造函数时同时修改列表

Sus*_*ant 5 java concurrency concurrentmodification

以下代码是否会引起ConcurrentModificationException副作用?

ArrayList<String> newList = new ArrayList<String>(list);
Run Code Online (Sandbox Code Playgroud)

考虑到列表的大小非常大,并且当上面的代码被执行时,另一个线程同时修改列表.

Gra*_*ray 8

编辑:

我的初始响应是肯定的,但正如@JohnVint正确指出的那样,它不会是一个ConcurrentModificationException因为在幕后ArrayList重复使用数组System.arrayCopy(...).请参阅最后的代码段.

问题是,在执行此复制时,另一个线程正在对元素数组进行更改.您可能会获得IndexOutOfBoundsException未初始化的数组值,甚至某种本机内存访问异常,因为System.arraycopy(...)在本机代码中完成.

在更新和复制期间,您需要在列表上进行同步以防止这些竞争条件,并建立内存屏障以确保备份的元素数组ArrayList是最新的.


public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    ...
}

// ArrayList
public Object[] toArray() {
        return Arrays.copyOf(elementData, size);
}

// Arrays
public static <T,U> T[] copyOf(U[] original, int newLength,
    Class<? extends T[]> newType) {
    ...
    System.arraycopy(original, 0, copy, 0,
        Math.min(original.length, newLength));
}

// System
public static native void arraycopy(Object src,  int  srcPos,
    Object dest, int destPos, int length);
Run Code Online (Sandbox Code Playgroud)

  • @Gray我想指出可能不存在`ConcurrentModificationException`,而不是`IndexOutOfBoundsException`底层副本是使用`System.arraycopy`而不是迭代器完成的.虽然你是对的,但仍会出现并发问题.它是两部分,1:得到ArrayList 2.`System.arraycopy`的大小,缺乏原子性将是这里的问题. (2认同)