ロック ブロックには、開始時と終了時 (ブロックの開始と終了) にメモリ フェンスが含まれます。これにより、メモリに対するすべての変更が他のコア (たとえば、他のコアで実行されている他のスレッド) から見えるようになります。あなたの例では、最初のロック ブロックの x、y、z への変更は、他のスレッドに表示されます。「可視」とは、レジスタにキャッシュされた値がメモリにフラッシュされ、CPU のキャッシュにキャッシュされたメモリが物理メモリにフラッシュされることを意味します。ECMA 334 は、ロック ブロックが Monitor.Enter と Monitor.Exit で囲まれたブロックであることを詳述しています。さらに、ECMA 335 は、Monitor.Enter が「揮発性の読み取り操作を暗黙的に実行するものとします...」と Monitor.Exit が「揮発性の書き込み操作を暗黙的に実行します。これは、変更が無効であることを意味します」と詳述しています。
これは事実上、lock ステートメントによって保護された変数を、その変更を他のスレッドから見えるようにするために volatile として宣言する必要がないことを意味します。
サンプル コードには、単一の共有アトミック操作 (y への単一の値の読み取りと書き込み) に依存する操作のみが含まれているため、次の方法でも同じ結果を得ることができます。
try
{
x = 10;
y = 20;
Thread.VolatileWrite(ref z, a + 10);
}
と
if(y == 10)
{
// ...
}
最初のブロックは、x への書き込みが y への書き込みの前に表示され、y への書き込みが z への書き込みの前に表示されることを保証します。また、x または y への書き込みが CPU キャッシュにキャッシュされていた場合、そのキャッシュがVolatileWrite の呼び出しの直後に物理メモリにフラッシュされる (したがって、他のスレッドから見えるようになる)ことも保証されます。
ブロック内でandを使用if(y == 10)して何かを行う場合は、キーワードの使用に戻る必要があります。xylock
さらに、以下は同一です。
try
{
x = 10;
y = 20;
Thread.MemoryBarrier();
z = a + 10;
}