あなたの質問に答えるために、あなたの例を詳しく見てみましょう。読み取りがいつ行われるかをより明確にするために、コードを少し調整しますboolIsFriday
。動作は同じです。これが私たちが持っているものです。
lock(obj_something)
{
boolFoo = true;
var register1 = boolIsFriday;
if (register1)
{
var register2 = anything;
doSomething(register2);
}
}
次に、このコードを矢印表記で装飾して、メモリ バリアがどこにあるかを視覚化します。↑ 矢印と ↓ 矢印を使用して、リリース フェンスと取得フェンスをそれぞれ表します。揮発性書き込みにはリリース セマンティクスがあるため、書き込みの前に ↑ が配置されます。揮発性読み取りはセマンティクスを取得するため、読み取りの後に↓ が配置されます。矢じりはすべてのものを遠ざけるものと考えてください。他の読み取りまたは書き込みは、矢印の頭を超えて上下に移動することはできません。今説明した用語で正確に考えると、これはメモリバリアが行っていることを正確に反映しているはずです. また、たまたま仕様に一致しているだけです。
始める前に、さらにいくつか言及する必要があります。まず、他のメモリ アクセスは矢印の頭を越えて移動することはできませんが、矢印の尾を越えて移動することはできます。繰り返しますが、これは仕様の文言に準拠しています。次に、メモリバリアが生成されると、それらは所定の位置にロックされます。ただし、揮発性の読み取りや書き込みなど、それらを生成するメカニズムは自由に移動できます。つまり、矢印は移動できませんが、対応する読み取りまたは書き込みは移動できます。3 番目に、alock
は完全なメモリ バリアを生成します。
ロック内のメモリアクセスは暗黙的に揮発性ですか?
この質問に答えるために、例に矢印表記を追加します。
↑
lock(obj_something)
↓
{
boolFoo = true;
var register1 = boolIsFriday;
if (register1)
{
var register2 = anything;
doSomething(register2);
}
↑
}
↓
矢印が配置されている場所に注意してください。他のメモリジェネレーターがない代わりに、lock
それらを注入するだけです。今明らかになるべきいくつかの事実があります。
- ロック ブロックの外側にあるメモリ アクセスは、ブロック内に移動できません。
- ロック ブロック内のメモリ アクセスはブロック外に移動できません。
- ロック ブロック内のすべてのメモリ アクセスは、ポイント #2 が満たされている限り、自由に移動できます。
これにより、質問の 1 つにすぐに答えられるはずです。いいえ。からボラティリティ セマンティクスを暗黙的に継承しませboolFoo
ん。現在、いくつかの制約はありますが、彼らはまだ自由に動き回ることができます。boolIsFriday
lock
boolFoo
では、とboolIsFriday
の両方が としてマークされている場合はどうなるでしょうかvolatile
。何が起こるか見てみましょう。
↑
lock(obj_something)
↓
{
↑
boolFoo = true;
var register1 = boolIsFriday;
↓
if (register1)
{
var register2 = anything;
doSomething(register2);
}
↑
}
↓
矢印が配置されていることに注意してください。書き込みの前に↑の矢印があり、boolFoo
他のメモリアクセスが揮発性書き込みを介してフロートダウンできないことを示しています。同様に、 の読み取りの後に ↓ 矢印がありboolIsFriday
、揮発性読み取りによって他のメモリ アクセスがフロートアップできないことを示します。現在明らかになっている2つの特異な事実があります。
- への書き込み
boolFoo
と読み取りがboolIsFriday
入れ替わる可能性があります。それを防ぐ矢印がないことに注意してください。
- への書き込み
boolFoo
は、ブロックの最後までフロートする可能性がありlock
ます (もちろん、メモリ バリアが生成されないと仮定しdosomething
ます。それ以上下がらないようにするロック ブロックを終了するのは ↑ 矢印です。
- の読み取りは
boolIsFriday
、ある時点で の読み取りと場所を交換する必要があるため、それほど遠くまでフロートダウンすることはできませんanything
。しかし、それが起こった場合、意味的にはanything
、揮発性の読み取りを表す ↓ を過ぎて浮かんでいるのと同じになります。動きが妨げられていることはすでに述べました。
ロックは式またはブロックの内容の最適化を制限しますか?
そして最後に、あなたが持っていた他の質問に答えます。キーワードは、lock
ロック式とロック ブロック自体の内容の両方に何らかの影響を与えます。これがどのように起こるかを見てみましょう。面白い表現のロック文を考案しました。
object foo;
lock (foo=bar)
{
// contents of lock here
}
私が何をしたか分かりますか?式に代入を入れました。そして、ここで何が起こっているのかをよりよく理解するために再編成すると、次のようになります。
object foo;
foo = bar;
object expression = foo;
↑
lock (expression)
↓
{
// contents of lock here
↑
}
↓
ここで、次のことに注意してください。
- ステートメントによって ↑ が生成されるため、 write to
foo
はフロートダウンできません。lock
これは、ロック式が影響した 1 つの方法です。
- ロック ブロックのコンテンツには、その動きに制約が課されるようになったことについては既に説明しました。
あなたの質問に答えるために、lock
キーワードはロック式とロックブロックの内容の両方に最適化の制約を課します。