我已阅读SO的以下文章
Difference between synchronization of field reads and volatile
这里提问者写道
同步点是确保值的 这个线程读取的acct.balance是当前的,也就是任何 对 acct.balance中对象字段的挂起写入也是 写入主存。
最受欢迎的答案:
你是对的。
请研究这段代码:
public class VolatileTest {
static/* volatile */boolean done = false;
public VolatileTest() {
synchronized (this) {
}
}
public static void main(String[] args) throws Exception {
Runnable waiter = new Runnable() {
public void run() {
while (!done)
;
System.out.println("Exited loop");
}
};
new Thread(waiter).start();
Thread.sleep(100); // wait for JIT compilation
synchronized (VolatileTest.class) {
done = true;
}
System.out.println("done is true ");
}
}
在我的电脑上,这个程序没有终止。
因此我认为
我说错了吗?
答案 0 :(得分:3)
synchronized
将看到更新的值,因为监视器释放发生在同一监视器由另一个线程获取之前。如果没有获取相同的监视器,其他线程可能会看到更新的值。你的配方中“唯一”太强了:)答案 1 :(得分:2)
你是对的)
此处描述了内存模型:Java Memory Model
特别指出:
监视器上的解锁发生在每次后续锁定之前 监视。
AND
对易失性字段(第8.3.1.4节)的写入发生在每次后续之前 阅读该领域。
因此,只有同一台显示器上的锁定和解锁才能表现出你想要的,也是所有写入和读取volatile变量的行为。因此,您的程序可能无法终止,因为您在没有锁定监视器的情况下阅读并且之前没有发生关系。
有一点需要注意(这就是多线程错误如此烦人的原因):
您可以在其他线程中看到更改。或者可能没有。在大多数体系结构中,您可能会在正常处理过程中看到它,并且在高负载期间可能会出现错误,从而难以重现。如果之前没有发生事件(即易失性,同步,在同一个线程或链接中的其他情况下),JVM不会保证什么时候会看到它,但是尝试它最好顺利运行。