我知道修改 ArrayList
让它不thread-safe .
➠ 但是,如果 ArrayList
未 被修改,可能通过调用 Collections.unmodifiableList
来保护, 正在调用 ArrayList::get
线程安全?
例如,可以将 ArrayList
传递给 Java Stream 吗?并行处理其元素?
最佳答案
But if the
ArrayList
is not being modified is callingArrayList::get
thread-safe?
不,它不是线程安全的。
如果您执行以下操作,则会出现问题:
- 线程 A 创建并填充列表。
- 线程 A 将对列表的引用传递给线程 B(没有发生在关系)
- 线程 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 returnedSpliterator
to another thread, which in turn may traverse or further split thatSpliterator
. 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 withtryAdvance()
, as certain guarantees (such as the accuracy ofestimateSize()
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/