java - 非易失性字段何时写入主存储器
问题描述
因为它done
是非易失性的,所以我希望线程 1 将继续执行并打印出“完成”。
但是当我运行程序时,这是控制台的输出
Done
Undo
这意味着线程 2 的更新被线程 1 看到了,对吧?(但done
不是一个易变的领域。)。
我的解释是线程 1 和线程 2 在同一个内核中运行。这样他们就可以看到提交的更新,如果我错了,请纠正我。
总的来说,我的问题是为什么线程1可以看到线程2的变化?这与 CPU 缓存回写/通过主内存有关吗?如果是,什么时候发生?
public class Done {
boolean done = true;
public void m1() throws InterruptedException {
while (this.done) {
System.out.println("Done");
}
System.out.println("Undo");
}
public void undo() {
done = false;
}
public static void main(String[] args) {
ExecutorService es = Executors.newCachedThreadPool();
Done v = new Done();
es.submit(() -> {
try {
v.m1();
} catch (InterruptedException e) {
e.printStackTrace();
}
}); // thread 1
es.submit(() -> {
v.undo();
}); // thread 2
es.shutdown();
}
}
解决方案
Java 内存模型的保证仅以一种方式起作用。如果某些事情得到保证,例如 volatile 写入的可见性,那么它将 100% 的工作。
如果没有保证,并不意味着它永远不会发生。有时其他线程会看到非易失性写入。如果您在具有不同 JVM 的不同机器上多次运行此代码,您可能会看到不同的结果。
推荐阅读
- c++ - 配置 Boost.Log v2
- rest - 如何将 XML 发送到 Jaspersoft?(数据适配器)
- kubernetes - 有状态应用程序的 Kubernetes 工作负载,但不需要永久磁盘
- r - str 输出中的 attr 信息并从数组中提取列名
- aws-lambda - 与 CloudFront 分配关联的 Lambda 函数无效或没有所需的权限
- java - 是否有 javafx.fxml.Initializable 的替代方法可以在场景开始时运行代码?
- pine-script - 如何进行 40 多个 security() 调用?
- c++ - 从文件读取并写入另一个文件时会打印乱码
- python - 姜戈。通过...分组。使用预先修改的列之一注释查询集
- python - 如何对列中的数据进行分组