3

本を読むと、次のコードが表示されます。

public class Test {

    private static boolean ready = false;
    private static int number = 0;

    public static class ListenerThread extends Thread {

        public void run() {

            while(!ready) {
                Thread.yield();
            }
            System.out.println(number);

        }

    }

    public static void main (String[] args) {

        new ListenerThread().start();
        number = 10;
        ready = true;

    }

}

私が驚いた主なポイントは、著者によって比較的迅速に言及されました。

  1. 彼らは、ListenerThreadが決して終了しないかもしれないと言いました。私はこれについて数日間(頭の後ろで)考えました、そして私の唯一の結論はそれがそのListenerThreadによってキャッシュされるかもしれないということです。本当?readyvolatileを作成すると、問題は解決しますか(キャッシュする必要がなくなったため)?

  2. また、プログラムが0を出力する可能性があるとも述べています。Javaが命令を並べ替える可能性があることを理解したので、番号が変更される前に別のスレッドに対してreadyがtrueになります。それらの命令を同期ブロックに配置する以外に、(中央ロック値で)問題を解決する方法(手法)はありますか?私はおそらくnotify()/ wait()を実装することを考えていましたが、同じ結果になると思います。問題を回避するための最良の方法は何ですか?

ありがとうございました!

編集:

たくさんのコードを読んだだけで、複数のスレッドでの並べ替えから保護するのに苦労した人はほとんどいません。これはどのくらい一般的ですか?

4

2 に答える 2

8

私の唯一の結論は、それがそのListenerThreadによってキャッシュされる可能性があるということです。本当?揮発性の準備をすることで問題は解決しますか(キャッシュする必要がなくなったため)?

キャッシュされるだけでなく、JITは、スレッドが値を変更しないことに基づいて値をインライン化できます。つまり、ハードコーディングされます。

volatileを使用すると、そのような仮定が行われるのを防ぐことができます。毎回キャッシュ整合性のあるコピーを読み取るように強制されます。

Javaが命令を並べ替える可能性があることを理解しました。

Javaだけでなく、CPUも命令を並べ替えることができます。JITは、CPUがこの並べ替えを実行できることを認識しており、CPUが適切に機能することを前提としているため、ほとんど必要ありません。

ところで、揮発性変数にアクセスすると、命令の並べ替えも防止されるため、ready揮発性にすることで両方の問題が解決します。

于 2013-01-14T15:35:24.817 に答える
3

彼らは、ListenerThreadが決して終了しないかもしれないと言いました。私はこれについて数日間考えました、そして私の唯一の結論はそれがそのListenerThreadによってキャッシュされるかもしれないということです。本当?揮発性の準備をすることで問題は解決しますか(キャッシュする必要がなくなったため)?

そうです、そうです。そして、はい、変数を宣言すると、変数volatileのメモリアクセスセマンティクスが変更され、変数にアクセスするたびに強制的に再読み取りが行われます。

また、プログラムが0を出力する可能性があるとも述べています。Javaが命令を並べ替える可能性があることを理解したので、番号が変更される前に別のスレッドに対してreadyがtrueになります。これらの2つの命令を同期ブロックに配置する以外に、問題を解決する方法はありますか?私はおそらくnotify()/ wait()を実装することを考えていましたが、同じ結果になると思います。

これは、順序付けの保証がないため、JVMは変数の割り当てを自由に並べ替えることができるためです。両方の当事者に等しく見えるようにしたい場合numberは、この並べ替えを防ぐ必要があります。@ PeterLawreyが言うように、readyこれには揮発性にするだけで十分です。

于 2013-01-14T15:26:26.167 に答える