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 = A
?B = 1
JLSは言う...
ただし、コンパイラーは、どちらかのスレッドの命令を並べ替えることができます。これが、そのスレッドの単独での実行に影響を与えない場合です。
...これは、命令がまだスワップされている可能性があることを示しています。一方、次のステートメント
モニターのロック解除が発生します-そのモニターの後続のすべてのロックの前に。
特定のスケジューリングでは、2つのスレッドのステートメント間に発生前の関係がある可能性があることを示します。これにより、おそらく命令の並べ替えが許可されなくなります。