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

在列表中添加元素时,为什么需要按照CopyOnWriteArrayList中的以下代码获取可重入锁.我们正在创建原始数组的副本,然后对其进行修改.如果我们不首先获得锁,我们会产生什么副作用?

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();
        }
    }
最佳答案
当您尝试在多线程上下文中对全局变量执行任何操作并且希望它既是原子的又要确保对其他线程的内存可见性时,您需要对该操作进行锁定.

在这里,getArray()返回一个全局实例字段Object []数组.

因此,在此示例中:

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

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

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

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

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

因此,当线程二使用setArray(newElements)设置线程一之后具有新值的新数组时,lenth索引处的较早数组值将被线程二设置的新元素覆盖.

相关文章

摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠...
摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠...
今天犯了个错:“接口变动,伤筋动骨,除非你确定只有你一个...
Writer :BYSocket(泥沙砖瓦浆木匠)微 博:BYSocket豆 瓣:...
本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程...