【发布时间】:2019-08-14 20:55:36
【问题描述】:
因为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();
}
}
【问题讨论】:
-
不保证可见性,但仍有可能。这就是非同步程序的问题:它们的输出是不可预测的。没有正确同步的程序几乎没有什么有用的结果。
-
My explanation is that thread 1 and thread 2 are running in the same core.您可能正在英特尔硬件上运行。英特尔的缓存是连贯的,这意味着更新甚至对其他内核也是可见的。因此,英特尔硬件提供了比 Java 更强大的可见性保证。为什么?我认为这是因为 Java 被设计为可移植的,它的设计者希望选择在不完全缓存一致的硬件上运行。
标签: java multithreading volatile