このプログラムは終了しません!
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]それは、メインメモリを協議するたびかのように-それが更新された値が表示され、私のプログラムが終了しますので。volatile
private int i = 0;
while (getI()...
私の質問は:私が作る場合
synchronized private int getI() {return i; }
驚くべきことに動作します!プログラムは終了します。
私は理解しsynchronized
ますが、ここで今までに入る唯一のスレッドがある-同時にメソッドに入るの2つの異なるスレッドを防止するのに使用されていますgetI()
。だから、これはどのような魔術のですか?
編集1
この(同期)オブジェクトの状態への変更がすべてのスレッドから見えることを保証
そうではなく、直接プライベート状態フィールドを持つよりもi
、私は、次の変更を加えました:
代わりにIでしたprivate int i = 0;
private Data data = new Data();
、に変更i = j
data.i = j
し、に変更return i
return data.i
今getI
とsetI
方法は、それらが定義されている(と同期させることができる)したオブジェクトの状態に何もしていません。今でも使用してsynchronized
終了するプログラムを引き起こしているキーワードを!楽しみは、その状態が実際に(変更されたオブジェクトがあることを知っているData
)、それに組み込まれて何の同期や何かを持っていません。それでなんで?
[1]それはおそらくちょうどます振る舞う何実際に、本当に起こることは私には不明である、そのよう
それはそれはJLSによって保証されていない、依存単なる偶然やプラットフォームに依存したり、特定のJVMです。だから、それに依存しません。