如何CopyOnWriteArrayList是线程安全的? [英] How can CopyOnWriteArrayList be thread-safe?

查看:394
本文介绍了如何CopyOnWriteArrayList是线程安全的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经查看了 OpenjDK源代码 CopyOnWriteArrayList ,似乎所有写操作都受到同一锁保护,读操作根本不受保护。据我所知,在JMM下,对变量(读和写)的所有访问都应该被锁保护,或者可能发生重排序效果。

I've taken a look into OpenJDK source code of CopyOnWriteArrayList and it seems that all write operations are protected by the same lock and read operations are not protected at all. As I understand, under JMM all accesses to a variable (both read and write) should be protected by lock or reordering effects may occur.

例如, set(int,E)方法包含这些行(在锁定下):

For example, set(int, E) method contains these lines (under lock):

/* 1 */ int len = elements.length;
/* 2 */ Object[] newElements = Arrays.copyOf(elements, len);
/* 3 */ newElements[index] = element;
/* 4 */ setArray(newElements);

get(int)另一方面,只有返回get(getArray(),index);

,这意味着 get 可能观察到数组在不一致的状态,如果语句1-4被重新排序像1-2(新)-4-2(copyOf)-3。

In my understanding of JMM, this means that get may observe the array in an inconsistent state if statements 1-4 are reordered like 1-2(new)-4-2(copyOf)-3.

我理解JMM是否不正确,或者为什么 CopyOnWriteArrayList 是线程安全的? >

Do I understand JMM incorrectly or is there any other explanations on why CopyOnWriteArrayList is thread-safe?

推荐答案

如果你查看基础数组引用,你会看到它被标记为 volatile 。当写操作发生时(如上面的提取),这个 volatile 引用只在最终语句中通过 setArray 。到此为止,任何读取操作都将返回数组 old copy 中的元素。

If you look at the underlying array reference you'll see it's marked as volatile. When a write operation occurs (such as in the above extract) this volatile reference is only updated in the final statement via setArray. Up until this point any read operations will return elements from the old copy of the array.

重要的是,更新是一个原子操作,因此读取将始终看到一个一致的状态的数组。

The important point is that the array update is an atomic operation and hence reads will always see the array in a consistent state.

只有取出锁的写操作的优点是改进读取的吞吐量:这是因为 CopyOnWriteArrayList 的写操作可能很慢,因为它们涉及复制整个列表。

The advantage of only taking out a lock for write operations is improved throughput for reads: This is because write operations for a CopyOnWriteArrayList can potentially be very slow as they involve copying the entire list.

这篇关于如何CopyOnWriteArrayList是线程安全的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆