5

私はJavaメモリモデルについて読んでおり、コンパイラがステートメントを再編成してコードを最適化できることを認識しています。

次のコードがあるとします。

long tick = System.nanoTime();
function_or_block_whose_time_i_intend_to_measure();
long tock = System.nanoTime();

コンパイラーは、私が測定しようとしているものが tick と tock の間で実行されないようにコードを再編成するでしょうか? 例えば、

long tick = System.nanoTime();
long tock = System.nanoTime();
function_or_block_whose_time_i_intend_to_measure();

もしそうなら、実行順序を維持する正しい方法は何ですか?

編集: nanoTime を使用した順不同の実行を示す例:

public class Foo {
    public static void main(String[] args) {
        while (true) {
            long x = 0;

            long tick = System.nanoTime();
            for (int i = 0; i < 10000; i++) { // This for block takes ~15sec on my machine
                for (int j = 0; j < 600000; j++) {
                    x = x + x * x;
                }
            }

            long tock = System.nanoTime();
            System.out.println("time=" + (tock - tick));
            x = 0;
        }
    }
}

上記のコードの出力:

time=3185600
time=16176066510
time=16072426522
time=16297989268
time=16063363358
time=16101897865
time=16133391254
time=16170513289
time=16249963612
time=16263027561
time=16239506975

上記の例では、最初の反復で測定された時間は、その後の実行で測定された時間よりも大幅に短くなっています。これは順不同の実行によるものだと思いました。最初の反復で何が間違っていますか?

4

2 に答える 2

0

コンパイラーは、私が測定しようとしているものが tick と tock の間で実行されないようにコードを再編成するでしょうか?

いいえ。それは決して起こらないでしょう。そのコンパイラーの最適化が失敗した場合、それは非常に深刻なバグになります。ウィキからの発言引用。

ランタイム (この場合、通常は動的コンパイラ、プロセッサ、およびメモリ サブシステムを指します) は、分離されたスレッドの結果がそれとまったく同じであることが保証されている限り、有用な実行の最適化を自由に導入できます。すべてのステートメントが、プログラム内でステートメントが発生した順序 (プログラム順序とも呼ばれる) で実行されていたはずです。

したがって、結果がプログラムの順序で実行された場合と同じである限り、最適化を行うことができます。あなたが引用した場合、最適化はローカルであり、このデータに関心のある他のスレッドはないと仮定します。これらの最適化は、コストがかかる可能性があるメイン メモリへのトリップの回数を減らすために行われます。これらの最適化で問題が発生するのは、複数のスレッドが関係しており、それらが互いの状態を知る必要がある場合のみです。

2 つのスレッドが互いの状態を一貫して確認する必要がある場合、揮発性変数またはメモリ バリア (同期) を使用して、メイン メモリへの書き込み/読み取りのシリアル化を強制できます。Infoq は、これについて興味深い記事を掲載しました。

于 2013-03-25T06:35:16.863 に答える
0

Java Memory Model (JMM) はhappens-before、プログラムのすべてのアクションで呼び出される部分的な順序付けを定義します。happens-before順序付けを確実にするために定義された 7 つのルールがあります。それらの1つは呼ばれProgram order ruleます:

番組順ルール。スレッド内の各アクションは、プログラム順序で後から来るそのスレッド内のすべてのアクションの前に発生します。

この規則に従って、コードはコンパイラによって並べ替えられません。

Java Concurrency in Practiceという本は、このトピックについて優れた説明を提供しています。

于 2013-03-25T08:31:56.247 に答える