2011-07-12 15 views
4

私の問題を説明するための基本的な例を使用して、私は2つのほぼ同じビットのコードを持っています。whileループとスレッディングの無限ループ問題

このコードにより、whileループが無限に実行されます。

private boolean loadAsset() { 
    new Thread(new Runnable() { 

     @Override 
     public void run() { 

      // Do something 
      loaded = true; 

     } 
    }).start(); 

    while (!loaded) { 
     // System.out.println("Not Loaded"); 
    } 
    System.out.println("Loaded"); 
    return false; 
} 

しかし(すなわち、whileループで何かをやって)このコードは、loaded変数が正常に評価されるようにするとwhile破るループと終了する方法を可能にします。

private boolean loadAsset() { 
    new Thread(new Runnable() { 

     @Override 
     public void run() { 

      // Do something 
      loaded = true; 

     } 
    }).start(); 

    while (!loaded) { 
     System.out.println("Not Loaded"); 
    } 
    System.out.println("Loaded"); 
    return false; 
} 

これはなぜ私に説明できますか?

+0

他のフィールドで変更できるフィールド値に頼っているのはなぜですか?あなたはブロックを同期している間に全体を作らなければならないかもしれません。 – Reddy

+2

''ロードされました '' volatile'ですか? – axtavt

答えて

6

「読み込まれました」が確実にvolatileとして宣言されていることを確認してください。

説明変数が複数のスレッドによって読み書きされている場合は、適切なスレッドセーフの対策を行う必要があります。そのようなスレッド安全対策の1つは揮発性であり、プリミティブ値(またはオブジェクト参照)に適しており、以前に読み取られた値に依存せず、所定の機会に書き込まれた値を「単純な」アクションとして読み書きされます。詳細については、Webサイトのvolatileに関する記事(スレッドセーフに関する一般的な情報とともに)があります。

+0

いいえ、説明はありませんか?うーん...ああ。 :) – mre

+0

申し訳ありませんが、説明が追加されました。 –

2

Memory Consistency Errorsを読んでください。基本的に、異なるスレッドは、同じデータでなければならないものの一貫性のないビューを持っています。これを解決するには、Synchronizationを読んでください。または、値が単一のスレッドによってのみ書き込まれているので、loadedvolatileと単に宣言します。

6

最初のループのみが無限に実行されます。実際には、CPUの100%を焼く「アクティブ待ち」を実行しています。そのため、OSやJVMはコンテキスト切り替えを行うことができず、他のスレッドを実行させることができません。

一方、System.out.println()では、I/Oが関与しているため、やや「非アクティブな待機」が発生します。 OSまたはJVMはコンテキストを切り替えることができ、他のスレッドは起動します。

あなたは10時間のあなたの最初のプログラムを実行したい場合、私はループがloadedが揮発性でない場合には、JITはレジスタにそれを置くことによって、それを最適化して自由ではなく、最終的

4

破ると確信しています毎回メモリから読み込みます。 2番目のケースでは、JITが毎回loadedをロードする必要がないと想定するにはループが複雑すぎます。

注:このコードは、コードを最適化するjavacコンパイラではありません。

+1

ニース。私はそれを知らなかった... –

0

私は、あなたがBusy Waitが空のループを経験していると思っています。それは眠らないでしょう。したがって、trueにロードされたスレッドは実行されません。