8

Java言語仕様(例17.4-1)によると、次のスニペット(で始まるA == B == 0)...

Thread 1             Thread 2
--------             --------
r2 = A;              r1 = B;
B = 1;               A = 2;

...結果としてr2 == 2とになる可能性がありr1 == 1ます。これは、実行の結果が実行B = 1;されたかどうかに依存しないr2 = Aため、JVMはこれら2つの命令の実行順序を自由に入れ替えることができるためです。つまり、仕様では次のインターリーブが許可されています。

Thread 1             Thread 2
--------             --------
B = 1;
                     r1 = B;
                     A = 2;
r2 = A;

これは明らかにとにr2 == 1なりr1 == 1ます。

私の質問:

例を少し微調整するとします。

Thread 1             Thread 2
--------             --------
r2 = A;              r1 = B;
monitorenter obj     monitorenter obj
monitorexit obj      monitorexit obj
B = 1;               A = 2;

ここobjで、はスレッド間で共有される参照です。

の並べ替えは引き続き許可されますかr2 = AB = 1


JLSは言う...

ただし、コンパイラーは、どちらかのスレッドの命令を並べ替えることができます。これが、そのスレッドの単独での実行に影響を与えない場合です。

...これは、命令まだスワップされている可能性があることを示しています。一方、次のステートメント

モニターのロック解除が発生します-そのモニターの後続のすべてのロックの前に。

特定のスケジューリングでは、2つのスレッドのステートメント間に発生前の関係がある可能性があることを示します。これにより、おそらく命令の並べ替えが許可されなくなります。

4

1 に答える 1

3

非公式には、許可されていません。これは「ゴキブリモーテルモデル」として知られています

http://jeremymanson.blogspot.com/2007/05/roach-motels-and-java-memory-model.html

特に、アクションを同期ブロック間で移動することはできません。

ただし、正式には、JMMは並べ替えに関して話しません。あなたの例では、私たちはそれを推論することができるだけです、

  1. 同期ブロック1は、同期ブロック全体の順序で同期ブロック2の前にあるため、r2=A発生します-前A=2; 0でなければなりません。ただし、と;r2の間に制約はありません。0または1にすることができます。B=1r1=Br1

  2. またはその逆。r10である必要があり、r20または2にすることができます。

したがって、プログラムにはまだデータ競合が含まれています。(r1,r2)それにもかかわらず、(0,0)、(1,0)、(0,2)のみであると推論することができます。(1,2)になることは不可能です

于 2013-01-03T21:28:31.050 に答える