4

次のステートメントを見てみましょう。

int d0, d1;
int[] ds = {0, 0};

これで、1つのスレッドに次の指示があります。

d0++;
d1++;

他のスレッドにはこの命令があります:

ds[1] = d1;
ds[0] = d0;

これらのスレッドを並行して実行する場合ds、{0、0}、{1、1}、および{1、0}のように見える3つの組み合わせが明らかにあります。

ここで大きな問題は、{0、1}も存在できるかということです。コンパイラ/JVMは、命令が無関係であると見なすため、命令を単純に交換できますか?はいの場合、そのような動作の「ルール」は正確には何であり、それはコンパイラーまたはJVM次第ですか?

4

3 に答える 3

6

はい、{0, 1}可能です。この場合、Javaメモリモデルは順序付けを保証するほど強力ではありません。これには、命令の並べ替えも必要ありません。これは、x86またはx86_64以外でプログラムを実行した場合に発生します。

ここで明確にするために、実際のCPUハードウェアは、x86の場合ではなく、これらのロードとストアを並べ替えます。

JavaメモリモデルのFAQを参照してください

于 2012-11-18T13:04:22.260 に答える
2

適切な同期がない場合、これは確かに可能です。

Java言語仕様では、第17章でマルチスレッドJavaプログラムのセマンティクスを定義しています。この章は理解するのがかなり難しいですが、信頼できる公式ルールが含まれています。特に、それは書きます

メモリモデルは、プログラムとそのプログラムの実行トレースが与えられた場合に、実行トレースがプログラムの合法的な実行であるかどうかを記述します。Javaプログラミング言語のメモリモデルは、実行トレース内の各読み取りを調べ、その読み取りによって監視された書き込みが特定のルールに従って有効であることを確認することによって機能します。

メモリモデルは、プログラムの可能な動作を記述します。実装は、プログラムのすべての結果の実行がメモリモデルによって予測できる結果を生成する限り、好きなコードを自由に生成できます。

大まかな概要を説明するために、メモリモデルは、発生前の関係を定義します。並べ替えは、と一致している必要があります。異なるスレッドによって実行されるアクションの発生前を確立する通常の方法は、これらのアクションを、たとえばブロックと同期synchronizedするか、揮発性変数への書き込みまたは揮発性変数から読み取ることです。

このような同期がない場合、ランタイムはスレッドを独立して実行し、現在のスレッドが監視できない並べ替えを許可します。

つまり、変更可能な共有状態がある場合は、通常、それにアクセスするスレッドを同期する必要があります。

于 2012-11-18T13:33:55.830 に答える
0

はい、コンパイラとjvm(ジャストインタイムコンパイラ)の両方で命令の並べ替えを実行できます。さらに、ハードウェアプロセッサが実行できます。不要な並べ替えを防ぐために、メモリバリア を使用する必要があります。

于 2012-11-18T13:09:48.547 に答える