我知道ArrayList
不是线程安全的,但我不确定这的确切含义。
如果是ThreadA
and ThreadB
两者都使用ArrayList
,哪些情况会导致问题并需要同步?
- 两个线程同时读取相同的索引
-
ThreadA
替换一个元素ThreadB
正在尝试同时访问,假设您不关心是否ThreadB
获取旧元素或新元素。
两个线程同时读取相同的索引
多个线程从公共线程读取数据是可以的ArrayList
if该列表是由分叉的线程构造的ThreadA
and ThreadB
并且该列表在线程分叉之前已完全构建并加载。
这样做的原因是线程和分叉它的线程的内存有一个发生之前的保证。例如,如果ThreadC
建立ArrayList
but after ThreadA
and ThreadB
是分叉的,那么不能保证 A 和 B 能够完全看到ArrayList
——如果有的话。
如果不是这种情况,那么您将需要同步列表。见下文。
ThreadA 更改 ThreadB 尝试同时访问的元素,假设您不关心 ThreadB 是否获取旧元素或新元素。
一旦您在并发设置中谈论对列表的修改,那么您必须在该列表上进行同步,否则无法保证修改将被发布,并且列表可能会部分发布,这可能会导致数据异常。正如@Marko 所说,其内部状态可能不一致。
您可以使用CopyOnWriteArrayList
它是为很少的更新和很多的读取而设计的,使用Collections.synchronizedList(...)
为了使您的列表受到保护,您可以始终以某种方式访问该列表synchronized
块(对于所有写入and读取),或者您可以切换到使用并发集合,例如ConcurrentSkipList
或者其他的东西。
ThreadA 更改 ThreadB 尝试同时访问的元素
这有点模棱两可。例如,如果您正在谈论将对象存储在列表中,然后更改恰好存储在列表中的对象,那么您不会遇到同步问题list但你会遇到同步问题object。如果列表的数据没有改变那就没问题了。但是,如果您需要保护该对象,则可以使用以下列表AtomicReference<YourObject>
, volatile
对象中的字段或其他同步需要确保更改在线程之间发布。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)