java - 多个volatile变量之间的同步

标签 java concurrency volatile

给定以下代码:

public class Test {

  private volatile boolean a;

  private volatile boolean b;

  private void one () {
    a = true;
    System.out.println (b);
  }

  private void two () {
    b = true;
    System.out.println (a);
  }

  public static void main (String[] args) throws Exception {
    Test s = new Test ();
    Thread one = new Thread (s::one);
    Thread two = new Thread (s::two);
    one.start ();
    two.start ();
    one.join ();
    two.join ();
  }

}

是否保证(在 Java 内存模型下)至少一个线程打印true

我知道写入 volatile 变量和读取更新值之间存在先行关系,但在我看来,有可能没有线程看到更新值,尽管我看不到让它发生。

最佳答案

是的,这是有保证的。

为了证明这一点,不失一般性地假设线程 1 打印 false。由于 b 是易变的,这意味着线程 1 在线程 2 写入 b 之前执行打印。但如果是这种情况,那么在线程 2 执行它自己的打印时,a 一定已经被线程 1 设置为 true

请注意,根据 JLS §17.4.5 写入之前不能重新排序打印件:

  • If x and y are actions of the same thread and x comes before y in program order, then hb(x, y) [x happens-before y].

此外,对ab 的写入将立即对其他线程可见:

  • A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.

关于java - 多个volatile变量之间的同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53619557/

相关文章:

java - 从 ArrayList 中删除重复的字符串

Java7/WatchEvent - 为什么它不是枚举?

Java ExecutorService 暂停/恢复特定线程

go - HTTP 处理程序中参与者模式的好处

java - 空的 synchronized(this){} 对线程之间的内存可见性有什么意义吗?

java - 比较和添加数组元素

git本地并发访问

c - 为什么将函数参数标记为 volatile

java - 在同步块(synchronized block)中访问的变量是否必须声明为 volatile?

java - 为什么下面的代码会导致线程争用