ArrayList并发访问 [英] ArrayList concurrent access
问题描述
我知道 ArrayList
不是线程安全的,但我不确定这个的确切含义。
I am aware that ArrayList
is not thread safe, but I'm unsure about the exact implications of this.
对于 ThreadA
和 ThreadB
都使用 ArrayList
,哪些情况会导致问题并需要同步?
In the case of ThreadA
and ThreadB
both using an ArrayList
, which of these situations will cause issues and necessitate synchronization?
- 两个线程同时读取相同的索引
-
ThreadA
替换ThreadB
同时尝试访问的元素,假设您不关心ThreadB
获取旧元素或新元素。
- Both threads simultaneously reading the same index
ThreadA
replacing an element whichThreadB
is attempting to access simultaneously, assuming that you don't care whether or notThreadB
gets the old or the new element.
推荐答案
两个线程同时读取相同的索引
Both threads simultaneously reading the same index
多个线程可以从常见的 ArrayList
中读取 / em>该列表是由分叉 ThreadA
和 ThreadB
的线程构建的,列表是完全构造和加载的在线程被分叉之前。
It is okay for multiple threads to be reading from common ArrayList
if the list was constructed by the thread that forked the ThreadA
and ThreadB
and the list is fully constructed and loaded before the threads were forked.
这样做的原因是有一个先前发生的保证,一个线程和分叉它的线程的内存。例如,如果 ThreadC
构建 ArrayList
,那么 之后 ThreadA
和 ThreadB
是分叉的,然后无法保证A和B将完全看到 ArrayList
- 如果有的话。
The reason for this is that there is a happens-before guarantee with a thread and the memory of the thread that forked it. If, for example, ThreadC
builds the ArrayList
but after ThreadA
and ThreadB
are forked, then there is no guarantee that A and B will fully see the ArrayList
-- if at all.
如果不是这种情况,则需要同步列表。请参阅下文。
If this is not the case then you will need to synchronize the list. See below.
ThreadA更改ThreadB尝试同时访问的元素,假设您不关心ThreadB是否获取旧元素或新元素。
ThreadA changing an element which ThreadB is attempting to access simultaneously, assuming that you don't care whether or not ThreadB gets the old or the new element.
一旦你谈到在并发设置中对列表的修改,那么你必须在该列表上同步无法保证修改将被发布,并且可能会部分发布可能导致数据异常的列表。正如@Marko所说,它的内部状态可能不一致。
Once you talk about modifications to the list in a concurrent setting, then you must synchronize on that list otherwise there is no guarantee that the modifications will be published and there are chances that the list could be partially published which could cause data exceptions. As @Marko puts it, its internal state may be inconsistent.
你可以使用设计的 CopyOnWriteArrayList
对于少数更新和许多读取,使用 Collections.synchronizedList(...)
使列表受到保护,您可以始终在中访问列表synchronized
块(对于所有写入和读取),或者您可以切换到使用并发集合,例如 ConcurrentSkipList
或某事。
You can either use a CopyOnWriteArrayList
which is designed for few updates and many reads, use Collections.synchronizedList(...)
to make your list be protected, you can access the list always in a synchronized
block (for all writes and reads), or you can switch to using a concurrent collection such as ConcurrentSkipList
or something.
ThreadA更改ThreadB试图同时访问的元素
ThreadA changing an element which ThreadB is attempting to access simultaneously
这有点含糊不清。如果您正在谈论,例如,在列表中存储对象,然后更改恰好存储在列表中的对象,那么您将不会在列表上出现同步问题但是您将与对象有同步问题。如果列表的数据没有变化那么它就没问题了。但是,如果您需要保护对象,则对象中的 AtomicReference< YourObject>
, volatile
字段列表,或者需要其他同步来确保在线程之间发布更改。
This is somewhat ambiguous. If you are talking about, for example, storing objects in the list and then changing the objects that happen to be stored in the list then you are not going to have a synchronization problem on the list but you will have a synchronization problem with the object. If the list's data is not changing then it will be fine. However, if you need to protect the object then either a list of AtomicReference<YourObject>
, volatile
fields in the object, or other synchronization is required to make sure the changes are published between the threads.
这篇关于ArrayList并发访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!