有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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的缓存副本,并且错过了更新

我也明白,如果我使volatileprivate 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

现在getIsetI方法对定义它们的对象的状态没有任何影响(可能是同步的)。即使现在使用synchronized关键字也会导致程序终止!有趣的是,知道状态实际上正在改变的对象(Data)没有同步或任何内置内容。那为什么


[1]它可能会表现得像那样,我不清楚到底发生了什么


共 (1) 个答案

  1. # 1 楼答案

    它只是巧合、平台依赖或特定的JVM依赖,JLS不保证这一点。所以,不要依赖它