gpt4 book ai didi

java - 仅在添加到 HashSet 时同步是线程安全的吗?

转载 作者:搜寻专家 更新时间:2023-11-01 01:59:18 25 4
gpt4 key购买 nike

想象有一个主线程创建一个 HashSet 并启动许多工作线程将 HashSet 传递给它们。

就像下面的代码:

void main() {
final Set<String> set = new HashSet<>();
final ExecutorService threadExecutor =
Executors.newFixedThreadPool(10);

threadExecutor.submit(() -> doJob(set));
}

void doJob(final Set<String> pSet) {
// do some stuff
final String x = ... // doesn't matter how we received the value.
if (!pSet.contains(x)) {
synchronized (pSet) {
// double check to prevent multiple adds within different threads
if (!pSet.contains(x)) {
// do some exclusive work with x.
pSet.add(x);
}
}
}
// do some stuff
}

我想知道仅在 add 方法上同步是否线程安全? contains 不同步会不会有什么问题?

我的直觉告诉我这很好,在离开同步块(synchronized block)后对 set 所做的更改应该对所有线程可见,但 JMM 有时可能违反直觉。

附言我不认为它是 How to lock multiple resources in java multithreading 的副本尽管这两个问题的答案可能相似,但这个问题针对的是更特殊的情况。

最佳答案

I'm wondering is it thread-safe to synchronize only on the add method? Are there any possible issues if contains is not synchronized as well?

简短的回答:否和是。

有两种解释方式:

直观的解释

Java 同步(以其各种形式)防止许多事情,包括:

  • 两个线程同时更新共享状态。
  • 一个线程试图读取状态,而另一个正在更新状态。
  • 线程看到陈旧值,因为内存缓存尚未写入主内存。

在您的示例中,同步add 足以确保两个线程不能同时更新HashSet,并且两个调用都将是在最近的 HashSet 状态上运行。

但是,如果 contains 也未同步,则 contains 调用可能会与 add 调用同时发生。这可能导致 contains 调用看到 HashSet 的中间状态,从而导致不正确的结果,或者更糟。如果调用不是同时发生的,这也会发生,因为更改没有立即刷新到主内存和/或读取线程没有从主内存读取。

内存模型解释

JLS 指定了 Java 内存模型,该模型规定了多线程应用程序必须满足的条件,以保证一个线程可以看到另一个线程所做的内存更新。该模型是用数学语言表达的,不容易理解,但要点是当且仅当从写入到后续读取之间存在一系列发生在之前的关系时,才能保证可见性。如果写入和读取在不同的线程中,则线程之间的同步是这些关系的主要来源。例如在

 // thread one
synchronized (sharedLock) {
sharedVariable = 42;
}

// thread two
synchronized (sharedLock) {
other = sharedVariable;
}

假设线程一代码在线程二代码之前运行,则在线程一释放锁和线程二获取锁之间存在先于关系。有了这个和“程序顺序”的关系,我们就可以构建一个从42的写入到赋值给other的链条。这足以保证 other 将被分配 42 (或者可能是变量的后续值)并且在 sharedVariable 中没有任何值 42 被写入其中。

如果 synchronized block 在同一个锁上同步,第二个线程可能会看到 sharedVariable 的陈旧值;即在 42 分配给它之前写入了一些值。

关于java - 仅在添加到 HashSet 时同步是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57360374/

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