我期待.foreach方法在CopyOnWriteArrayList中的java 11实现。
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (Object x : getArray()) {
@SuppressWarnings("unchecked") E e = (E) x;
action.accept(e);
}
}我看到它只是循环数组,没有任何锁。add()或remove()能否与foreach同时执行,从而给出ConcurrentModificationException?与iterator()不同,foreach似乎避免在写时使用原始数组的副本,而且不使用锁。
发布于 2022-05-19 13:39:19
可以使用
foreachofCopyOnWriteArrayList导致ConcurrentModificationException在java中吗?
不是的。从代码中可以看出,它不会抛出ConcurrentModificationException
public void forEach(Consumer<? super E> action) {
Objects.requireNonNull(action);
for (Object x : getArray()) {
@SuppressWarnings("unchecked") E e = (E) x;
action.accept(e);
}
}注意,getArray()调用没有复制数组。声明如下:
private transient volatile Object[] array;
final Object[] getArray() {
return array;
}(因为array是volatile,所以不需要锁来确保getArray()返回当前版本的数组。)
与
foreach同时执行的add()或remove()能给出一个ConcurrentModificationException吗?
对这些方法的调用将导致与更新一起创建一个新的支持数组。这是在CopyOnWriteArrayList上保持一个锁,然后替换数组。
同时,foreach()调用将在旧数组上循环,好像什么都没有发生一样。
与
相比,foreach似乎避免在写时使用原始数组的副本,并且不使用锁。
实际上,iterator()的行为方式与foreach相同。它调用getArray()来获取当前的支持数组。
public Iterator<E> iterator() {
return new COWIterator<E>(getArray(), 0);
}如果您查看COWIterator类,它也不会抛出ConcurrentModificationException。
注意,这都是在javadocs中指定的。
CopyOnWriteArrayList状态的javadocs:“.迭代器保证不会抛出ConcurrentModificationException."
foreach的javadocs (在Iterable中)状态:“默认实现的行为方式如下:”
用于(T :这个) action.accept(t);
它使用的是CopyOnWriteArrayList提供的不抛出ConcurrentModificationException的迭代器;参见1。
然而,有一个小问题。CopyOnWriteArrayList的子列表不是CopyOnWriteArrayList,它可以生成ConcurrentModificationException;参见CopyOnWriteArrayList throwing CurrentModificationException
https://stackoverflow.com/questions/72305316
复制相似问题