7

以下の Java の例を考えてみましょう。どちらのクラス メンバー変数も宣言されていないことに注意してくださいvolatile。メモリ モデルと "前に起こる" ルールを正しく理解している場合、Java 実装はrun()メソッドを最適化して、別のスレッドがメソッドを呼び出した場合でもメソッドが永久に実行されるようにすることができstopNow()ます。これは、スレッドに複数回run()の値の読み取りを強制するメソッドが何もないために発生する可能性があります。stopあれは正しいですか?そうでない場合、なぜですか?

class Example implements Runnable {
    boolean stop = false;
    int value = 0;

    public void stopNow() {
       stop = true;
    }

    public int getValue() {
        return value;
    }

    @Override
    public void run() {
        // Loop until stop is set to true.
        while (!stop) {
            ++value;
        }
        return;
    }
}
4

2 に答える 2

4

これは別のスレッドで変更できますが、これは保証されません。また、これはスレッドセーフでもありません。別のスレッドから見えるように変数を保証するには、次のいずれかを行う必要があります

1 つのスレッドによって行われたフィールドへの変更は、次の条件下でのみ、他のスレッドに表示されることが保証されています。

  • 書き込みスレッドが同期ロックを解放し、その後、読み取りスレッドが同じ同期ロックを取得します。
  • フィールドが volatile として宣言されている場合、書き込みスレッドがさらにメモリ操作を実行する前に、そのフィールドに書き込まれた値はすべてフラッシュされ、書き込みスレッドによって可視になります
    (つまり、当面の目的のため
    にすぐにフラッシュされます)。リーダー スレッドは、
    アクセスのたびに volatile フィールドの値を再読み込みする必要があります。
  • スレッドがオブジェクトのフィールドに初めてアクセスすると、フィールドの初期値または他のスレッドによって書き込まれた値が表示されます。
  • スレッドが終了すると、書き込まれたすべての変数がメイン メモリにフラッシュされます。たとえば、あるスレッドが Thread.join を使用して別のスレッドの終了時に同期する場合、
    そのスレッドによって行われた効果を見ることが保証されます (§4.3.2 を参照)。

役立つSOスレッド

于 2014-02-05T04:28:49.653 に答える
2

そのとおりです。これが、 を使用する理由の 1 つですvolatile

于 2014-02-05T04:26:40.950 に答える