2

本「Java Concurrency in Practice」で次の例に出くわしました。

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;
     }
}

さらに次のように述べられています。

ready の値がリーダー スレッドに表示されない可能性があるため、NoVisibility は永久にループする可能性があります。さらに奇妙なことに、NoVisibility はゼロを出力する可能性があります。これは、ready への書き込みが number への書き込みの前にリーダー スレッドに表示される可能性があるためです。これは、並べ替えと呼ばれる現象です。

並べ替えの問題は理解できますが、可視性の問題は理解できません。の値がreadyリーダースレッドに表示されないのはなぜですか? メイン スレッドが に値を書き込むとready、遅かれ早かれリーダー スレッドが実行され、 の値を読み取ることができますready。メインスレッドによって行われた変更がreadyリーダースレッドに表示されないのはなぜですか?

4

2 に答える 2

1

ReaderThreadのメソッドは、値がそのスレッドの外部で変更されないことを自由に想定して最適化できるためrun()、 の最新の値が表示されない場合があります。の宣言readyにキーワードvolatileを追加するなど、言語の関連する同時実行機能を使用することで、この仮定を取り除くことができます。ready

于 2015-07-26T04:52:05.683 に答える
1

これは、マルチコア CPU と個別の CPU キャッシュで発生し始めた新しい問題だと思います。

実際にメモリを読み取ったり変更したりする場合は心配する必要はありません。複数の CPU を使用していても、各 CPU に独自のキャッシュがあることを除けば安全です。メモリの場所はキャッシュされ、他のスレッドはキャッシュから排他的に動作するため、それを見ることはありません。

揮発性にすると、両方のスレッドが毎回直接メモリに移動するように強制されるため、処理がかなり遅くなりますが、スレッドセーフです。

于 2015-07-26T06:30:04.697 に答える