java为什么同步getter像volatile read一样工作?
此程序不会终止
public class Main extends Thread {
private int i = 0;
private int getI() {return i; }
private void setI(int j) {i = j; }
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
main.start();
Thread.sleep(1000);
main.setI(10);
}
public void run() {
System.out.println("Awaiting...");
while (getI() == 0) ;
System.out.println("Done!");
}
}
我理解这种情况,因为运行Awaiting
循环的CPU核心总是看到i
的缓存副本,并且错过了更新
我也明白,如果我使volatile
private int i = 0;
,那么while (getI()...
的行为将[1]就好像每次它都在查阅主内存一样,因此它将看到更新的值,我的程序将终止
我的问题是:如果我
synchronized private int getI() {return i; }
它出人意料地有效!!程序终止
我知道synchronized
用于防止两个不同的线程同时进入一个方法,但这里只有一个线程进入getI()
。这是什么魔法
编辑1
This (synchronization) guarantees that changes to the state of the object are visible to all threads
因此,我没有直接使用私有状态字段i
,而是做了以下更改:
代替private int i = 0;
我做了private Data data = new Data();
,{改为data.i = j
,{改为return data.i
现在getI
和setI
方法对定义它们的对象的状态没有任何影响(可能是同步的)。即使现在使用synchronized
关键字也会导致程序终止!有趣的是,知道状态实际上正在改变的对象(Data
)没有同步或任何内置内容。那为什么
[1]它可能会表现得像那样,我不清楚到底发生了什么
# 1 楼答案
它只是巧合、平台依赖或特定的JVM依赖,JLS不保证这一点。所以,不要依赖它