ArrayList 并发访问 [英] ArrayList concurrent access

查看:41
本文介绍了ArrayList 并发访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 ArrayList 不是线程安全的,但我不确定这的确切含义.

I am aware that ArrayList is not thread safe, but I'm unsure about the exact implications of this.

ThreadAThreadB 都使用 ArrayList 的情况下,哪些情况会导致问题并需要同步?

In the case of ThreadA and ThreadB both using an ArrayList, which of these situations will cause issues and necessitate synchronization?

  1. 两个线程同时读取同一个索引
  2. ThreadA 替换 ThreadB 尝试同时访问的元素,假设您不关心 ThreadB 是否变旧或新元素.
  1. Both threads simultaneously reading the same index
  2. ThreadA replacing 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.

推荐答案

两个线程同时读取同一个索引

Both threads simultaneously reading the same index

多个线程可以从共同的ArrayList读取如果列表是由分叉ThreadAThreadB 并且在分叉线程之前完全构造并加载了列表.

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.

这样做的原因是一个线程和分叉它的线程的内存有一个happens-before保证.例如,如果 ThreadC 构建了 ArrayListafter ThreadAThreadB 是分叉,则不能保证 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

这有点模棱两可.例如,如果您正在谈论将对象存储在列表中,然后更改碰巧存储在列表中的对象,那么您将不会在 列表 上遇到同步问题,但您会对象有同步问题.如果列表的数据没有改变,那就没问题了.但是,如果您需要保护对象,则需要对象中的 AtomicReferencevolatile 字段列表或其他同步,以确保更改是在线程之间发布.

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屋!

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