首页 > 解决方案 > 为什么同步的 getter 像 volatile 读取一样工作?

问题描述

该程序不会终止!

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并错过更新。

我也明白,如果我这样做,那么它的行为[1]就好像每次它都在查询主内存一样 - 所以它会看到更新的值并且我的程序将终止。volatileprivate int i = 0;while (getI()...

我的问题是:如果我做

synchronized private int getI() {return i; }

它出奇的有效!!程序终止。

我知道这synchronized用于防止两个不同的线程同时进入一个方法 - 但这里只有一个线程进入getI()。那么这是什么法术呢?

编辑 1

这(同步)保证对象状态的变化对所有线程都是可见的

因此,我没有直接拥有私有状态字段i,而是进行了以下更改:

代替private int i = 0;I did private Data data = new Data();i = j更改为data.i = jreturn i更改为return data.i

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


[1]它可能只是表现得那样,实际上,真正发生的事情我不清楚

标签: javamultithreadingsynchronizedvolatile

解决方案


这只是巧合或平台相关或特定 JVM 相关,JLS 不保证。所以,不要依赖它。


推荐阅读