Java CopyOnWriteArrayList是如何用副本替换原始数组的?何时发生?

Java CopyOnWriteArrayList是如何用副本替换原始数组的?何时发生?,java,Java,根据CopyOnWriteArrayList JavaDoc: java.util.ArrayList的线程安全变体,其中所有 通过创建新的 基础数组的副本 每个线程总是在变异后处理自己的本地副本吗 我认为副本应该替换原始阵列。如何用原始数组替换副本以供其他线程使用,以及在什么阶段会发生这种情况?如果您查看集合实现,它将使用现有元素创建新对象数组,并在操作后替换新数组 /** * Replaces the element at the specified position in this li

根据CopyOnWriteArrayList JavaDoc:

java.util.ArrayList的线程安全变体,其中所有 通过创建新的 基础数组的副本

每个线程总是在变异后处理自己的本地副本吗


我认为副本应该替换原始阵列。如何用原始数组替换副本以供其他线程使用,以及在什么阶段会发生这种情况?

如果您查看集合实现,它将使用现有元素创建新对象数组,并在操作后替换新数组

/**
 * Replaces the element at the specified position in this list with the
 * specified element.
 *
 * @throws IndexOutOfBoundsException {@inheritDoc}
 */
public E set(int index, E element) {
    synchronized (lock) {
        Object[] elements = getArray();//creating the new array with ting vaue
        E oldValue = elementAt(elements, index);

        if (oldValue != element) {
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len);
            newElements[index] = element;
            setArray(newElements);//replacing the old array
        } else {
            // Not quite a no-op; ensures volatile write semantics
            setArray(elements);
        }
        return oldValue;
    }
}
以相同的方式实现add和remove方法 因为所有这些方法都是线程安全的,所以假设两个线程都使用add方法,那么两个线程都有自己的元素副本

从文件:

快照样式迭代器方法使用对创建迭代器时数组状态的引用。该数组在迭代器的生命周期内不会更改,因此不可能发生干扰,并且迭代器保证不会抛出ConcurrentModificationException。自创建迭代器以来,迭代器不会反映对列表的添加、删除或更改


它不会合并回主阵列。数据结构中有一个指向数组的指针,该数组被更改为指向新数组。您已经有了源代码。为什么不看看它,看看它是如何工作的呢?是的@Andreas,我在发布后和发布前都看到了源代码。但是,还不完全清楚。add方法在操作前已锁定,在add操作完成后已解锁。要确认为什么add处理的是副本而不是主阵列。我认为原因是迭代器在主数组上工作,如果没有在副本上完成add,那么它可能抛出CME。请建议我的理解是否正确?你是正确的。在副本(包括新值)完成之前,您无法使其对其他线程可见。-请注意,您的问题措辞错误。没有进行合并,也没有主数组。一旦复制和更新操作完成,更新的副本将替换原始数组,此时所有其他线程都将看到它。@Andreas,我已经更新了问题