なぜ、揮発性の読み取りなどの同期ゲッター仕事?

好奇心旺盛:

このプログラムは終了しません!

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!");
  } 
}

私は、実行中のCPUコアので、これが起こる理解Awaitingループは常にのキャッシュされたコピーを見てi、更新をミス。

私はまた私が作る場合ということを理解その後、動作します[1]それは、メインメモリを協議するたびかのように-それが更新された値が表示され、私のプログラムが終了しますので。volatileprivate int i = 0;while (getI()...

私の質問は:私が作る場合

synchronized private int getI() {return i; }

驚くべきことに動作します!プログラムは終了します。

私は理解しsynchronizedますが、ここで今までに入る唯一のスレッドがある-同時にメソッドに入るの2つの異なるスレッドを防止するのに使用されていますgetI()だから、これはどのような魔術のですか?

編集1

この(同期)オブジェクトの状態への変更がすべてのスレッドから見えることを保証

そうではなく、直接プライベート状態フィールドを持つよりもi、私は、次の変更を加えました:

代わりにprivate int i = 0;Iでしたprivate Data data = new Data();i = jに変更data.i = jし、return iに変更return data.i

getIsetI方法は、それらが定義されている(と同期させることができる)したオブジェクトの状態に何もしていません。今でも使用してsynchronized終了するプログラムを引き起こしているキーワードを!楽しみは、その状態が実際に(変更されたオブジェクトがあることを知っているData)、それに組み込まれて何の同期や何かを持っていません。それでなんで?


[1]それはおそらくちょうどます振る舞う何実際に、本当に起こることは私には不明である、そのよう

xingbin:

それはそれはJLSによって保証されていない、依存単なる偶然やプラットフォームに依存したり、特定のJVMです。だから、それに依存しません。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=190044&siteId=1