在CopyOnWriteArrayList中获取用于添加操作的锁

时间:2019-04-13 15:51:31

标签: java multithreading reentrantlock

当在Reentrant中添加元素时,为什么需要根据CopyOnWriteArrayList中的以下代码获取List锁。我们正在创建原始数组的副本,然后对其进行修改。如果不首先获得lock,我们会有什么副作用?

public boolean add(E e) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            newElements[len] = e;
            setArray(newElements);
            return true;
        } finally {
            lock.unlock();
        }
    }

1 个答案:

答案 0 :(得分:2)

当您尝试在多线程上下文中对全局变量进行任何操作时,希望它既是 atomic ,又要确保内存可见性对其他线程的作用需要锁定该操作。

此处getArray()返回一个全局实例字段Object[] array

因此在此示例中:

Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;

如果此代码块周围没有锁,并且假设有两个线程试图添加一个元素,则在这种情况下,可能发生线程1和线程2都读取{的 same 值的情况。 {1}}并将新元素分配给相同的索引。

因此哪个线程在最后分配新值将覆盖另一个线程先前设置的值。

为进一步说明,假设线程1和线程2读取了相同的len值,现在线程1继续从len创建新数组并分配变量{{1 }}放在新数组的Arrays.copyOf(elements, len + 1)位置。

在线程可以使用e线程设置新数组之前,线程2同时使用相同的len值继续此过程。尽管它将创建一个新的数组实例,但是设置新元素的索引将与线程一使用的setArray(newElements)相同。

因此,当线程2使用len将新数组设置为线程1之后的新值时,在len th 索引处的较早数组值将被覆盖。通过线程2设置新元素。

相关问题