2016-12-03 7 views
2

私は、コンパイラの最適化のためにコード実行を並べ替えることで、ReaderThreadを無限ループにすると言っている本を読みました。そんなことがあるものか?Javaマルチスレッドの可視性?

public class NoVisibility { 
private static boolean ready; 
private static int number; 
private static class ReaderThread extends Thread { 
    public void run() { 
     while (!ready) 
      Thread.yield(); 
     System.out.println(number); 
     } 
    } 
    public static void main(String[] args) { 
     new ReaderThread().start(); 
     number = 42; 
     ready = true; 
    } 
} 
+0

上記のコードを実行しようとしましたか?私はEclipseでJRE-8を実行したときに無限ループに入っていません。 – AADProgramming

+0

@AADTechnical - それは何も証明しません。要点は、JLS *がそのコードに無限ループを許すことです。私の答えを見てください。 –

+0

@AADTechnicalはいデスクトップPCで5つのReaderThreadsを実行したところ、完全に実行されました(印刷42)。しかし、それはコンパイラの設定と私が推測するCPUに依存します。これは、「Java Concurrency in Action」の例です。 – sonnywang

答えて

4

これはどのように可能ですか?

Java言語仕様(JLS)が可能であるため、コードの並べ替えは(一般的に)可能です。しかし、並べ替えは(おそらく)ここで問題になることはありません。むしろ、無限ループは、ハードウェアメモリキャッシュの挙動に起因する可能性が高い。この場合

は子スレッドに見えるようにmain方法で製造された変数にの書き込みが必要であることをJLSには何もありません。技術的な説明は、が起こる前に、チェーンが(後続の)読み取りへの書き込みをリンクする前に起こるということです。重大な問題がなければ、の直前にチェーンが存在することを保証するものではありません。

ここで実際に無限ループが存在するかどうかは、あらゆる種類の要因に依存することに注意してください。要点は、サンプルコードの記述方法を考えれば可能であるということです。

+0

ありがとう、スティーブン。それは、子スレッドが変数 "ready"のコピーまたはキャッシュを調べて、メインスレッドによる変更が見えないことを意味しますか?子スレッドが無限ループに陥る可能性はありません。ちょっと興味があるんだけど。 – sonnywang

+0

それは一つの可能​​性です。もう1つは、メインスレッドが書き込みをフラッシュしないことです。他のハードウェアアーキテクチャーについて他の説明がないという理論的な理由はありません。 –

+0

これを理解する正しい方法は、H-B関係の観点から考えることです。キャッシュは、/特定のハードウェア上で実行されているプログラムで必要な動作を実装するメカニズムだけである/メモリバリアをフラッシュします。 –

-1

おそらくCPUキャッシュによって発生します。 ReaderThreadは、 "ready"変数の古い値を見るかもしれないので、whileループを壊さないかもしれません。旧式の「準備完了」値は古いデータと呼ばれます。

+0

なぜダウン投票?これはJava Concurrency in Actionの本で書かれた説明です。 – sonnywang