gpt4 book ai didi

java - 即使只有一个编写器线程, volatile 也会出现问题

转载 作者:行者123 更新时间:2023-12-02 10:01:22 27 4
gpt4 key购买 nike

如果只有一个写入器线程和一个读取器线程,我们仍然可以与 volatile 变量发生竞争条件。就像下面的代码一样,在一种情况下,编写器线程将 x 的值检查为 0,但不会发生任何上下文切换,并且读取器线程也将 x 值视为 0。虽然在一种情况下,编写器线程检查 x 的值为零,然后将其增加 1 将其刷新到主内存(因为 x 是 volatile 的),但会发生上下文切换,并且读取器线程将 x 值视为 1。我只是想知道在这个用例中 volatile 是否足够,或者我们需要使用同步来避免竞争条件

我尝试执行下面的代码,但它总是给我相同的结果

public class VolatileSingleWriterClarity {
static volatile int x = 0;

public static void main(String[] args) {
new Thread(VolatileSingleWriterClarity::writer).start();
new Thread(VolatileSingleWriterClarity::reader).start();
}

public static void reader() {
System.out.println(x);
}

public static void writer() {
x++;
}
}

最佳答案

Like in the code below is it possible that in one case the writer thread checks value of x as zero does nothing context switch occurs and reader thread also see's x value as 0.

是的,这绝对有可能。尽管x是 volatile 的,x++涉及两个完全独立的操作: volatile 读取,然后是 volatile 写入。这些操作中的每一个都是原子的,但是它们之间绝对有可能发生上下文切换。 (两个线程也可以在完全独立的处理器内核上运行,因此即使没有上下文切换,读取器也可以在写入器即将写入新值时读取原始值.)

<小时/>

I was just wondering whether volatile would be sufficient in this use case or we need to go with synchronized to avoid race condition

synchronized 在这里并没有真正的帮助。您似乎担心防止这种情况( volatile 允许,但同步可以防止):

  • 编写器线程读取x的原始值
  • 读取器线程读取x的原始值,并将其打印
  • 编写器线程写入 x 的新值,但永远不会被读取

但它与此场景完全相同( volatile 同步都允许):

  • 读取器线程读取x的原始值,并将其打印
  • 编写器线程读取x的原始值
  • 编写器线程写入 x 的新值,但永远不会被读取

因此,在不修复另一个的情况下“修复”一个是没有意义的。

如果您想确保读取器线程在写入器线程写入之前不会读取 x ,您需要做一些更复杂的事情,例如使用等待通知

关于java - 即使只有一个编写器线程, volatile 也会出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55605199/

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