java - 多个 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
必须已经被true
线程 1 设置为。
请注意,根据JLS §17.4.5,在写入之前无法重新排序打印件:
- 如果x和y是同一线程的操作,并且x在程序顺序中位于y之前,则hb(x, y) [ x发生在y之前]。
此外,写入a
或b
将立即对另一个线程可见:
- 对该字段的写入
volatile
(第 8.3.1.4 节)发生在对该字段的每次后续读取之前。
推荐阅读
- java - 游戏机:我应该为应用内购买推出内部测试吗?
- html - Favicon 不会显示在视图源或图像中。(本地主机铬)
- delphi - 为什么使用 GetTempPath/GetTempFileName 时顺序很重要?
- sql - Oracle SQL 排除异常值
- python - 在应用程序启动后修改 SQLALCHEMY_DATABASE_URI
- powershell - 如何保护PowerShell中的连接字符串密码?
- python - 如何提高这个脚本速度?
- ios - 执行核心数据迁移时如何获取关系实体?
- python - 如何修复 Google Cloud 上的 YouTube-dl 无效参数?
- apk - 有什么办法可以将.exe文件更改为.apk?