1

これで悪いことをしている場合は申し訳ありませんが、この質問のスピンオフである質問があります:

java 5+のvolatileがキャッシュされた変数のコピーをメインメモリと同期しないのはなぜですか?

基本的に、変数volatileから を削除するとどうなるかを見たかったのです。a私の変更が適用された元の質問のコードは次のとおりです。

public class Test {
    //volatile static private int a;
    static private int a;
    static private int b;
public static void main(String [] args) throws Exception {
    for (int i = 0; i < 100; i++) {
        new Thread() {

            @Override
            public void run() {
                int tt = b; // makes the jvm cache the value of b

                while (a==0) {

                }
                //some threads never get here (past the a==0 loop)

                if (b == 0) {
                    System.out.println("error");
                }
            }

        }.start();
    }

    b = 1;
    a = 1;
}
}

私のラップトップ (Win 7 64、JVM ビルド 1.7.0_04-b22) で何が起こるかというと、volatile. コンソール出力をさらに追加すると、100 個のスレッドのほとんどが最終的にaから0への変更を認識しますが、ループ1を実行し続ける少数 (10 未満) が常に残っていることがわかりました。a==0

私の質問は、これらのスレッドも最終的にその変更を確認するのでしょうか? はいの場合、同様のスレッドの大部分と比較して、それを行うのに数万倍の時間がかかるのは正常ですか? どうして?

4

2 に答える 2

7

これは、変数の伝播速度に関するものではありません。マシンコードは、メモリ書き込みが試行されないようなものである可能性があります。値はレジスターに存在する可能性があります。

とにかく、私の提案は壊れた Java コードの振る舞いを調査することではありません。代わりに、正しく同期されたプログラムを作成する方法を学んでください。Java メモリ モデルを詳細に調べて、その保証を理解してください。JMM の保証は、それらの保証を維持する実際の JVM 実装コードからかなり離れており、JMM は、JVM にあらゆる種類の最適化を適用する自由を与えるために特別に作成されました。

特に痛烈な例として、壊れたコードの動作が実行中に変化する可能性があります。これは、解釈されたコードまたは C1 コードがジャストインタイムで C2 コードに置き換えられるためです。あなたが参照しているプログラムを実行することから学ぶことは何もありません。

于 2013-08-19T11:05:18.243 に答える