gpt4 book ai didi

java - `ArrayList::get` 是线程安全的吗?

转载 作者:行者123 更新时间:2023-12-03 12:59:23 25 4
gpt4 key购买 nike

我知道修改 ArrayList让它不thread-safe .

➠ 但是,如果 ArrayList 被修改,可能通过调用 Collections.unmodifiableList 来保护, 正在调用 ArrayList::get线程安全?

例如,可以将 ArrayList 传递给 Java Stream 吗?并行处理其元素?

最佳答案

But if the ArrayList is not being modified is calling ArrayList::get thread-safe?

不,它不是线程安全的。

如果您执行以下操作,则会出现问题:

  1. 线程 A 创建并填充列表。
  2. 线程 A 将对列表的引用传递给线程 B(没有发生在关系)
  3. 线程 B 在列表中调用 get

除非在 1 和 3 之间有适当的 happens before 链,否则线程 B 可能会看到陈旧的值......偶尔......在某些平台上在某些工作负载下。

有很多方法可以解决这个问题。例如,如果线程 A 在步骤 1 之后启动了线程 B,那么就会有一个 happens before。类似地,如果 A 通过正确同步的 setter/getter 调用或 volatile 变量将列表引用传递给 B,则会发生之前的情况。

但底线是(只是)不更改列表不足以使其成为线程安全的。


... perhaps protected by a call to Collections.unmodifiableList

Collections.unmodifiableList 的创建应该提供happens before 关系...前提是您通过包装而不是直接通过ArrayList 访问列表: :get.


For example, can an ArrayList be passed to a Java Stream for parallel-processing of its elements?

这是一个特定的情况。流机制将提供happens before 关系。 前提是它们按预期使用。这很复杂。

这来自Spliterator 接口(interface)javadoc .

"Despite their obvious utility in parallel algorithms, spliterators are not expected to be thread-safe; instead, implementations of parallel algorithms using spliterators should ensure that the spliterator is only used by one thread at a time. This is generally easy to attain via serial thread-confinement, which often is a natural consequence of typical parallel algorithms that work by recursive decomposition. A thread calling trySplit() may hand over the returned Spliterator to another thread, which in turn may traverse or further split that Spliterator. The behaviour of splitting and traversal is undefined if two or more threads operate concurrently on the same spliterator. If the original thread hands a spliterator off to another thread for processing, it is best if that handoff occurs before any elements are consumed with tryAdvance(), as certain guarantees (such as the accuracy of estimateSize() for SIZED spliterators) are only valid before traversal has begun."

换句话说,线程安全是 Spliterator 实现和 Stream 实现的共同责任。

考虑这一点的简单方法是“奇迹发生了”......因为如果没有发生,那么并行流将无法使用。

但请注意,Spliterator 根本不需要使用 ArrayList::get

关于java - `ArrayList::get` 是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46614481/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com