Joe Duffy、CLR 2.0+メモリモデルを説明する6つのルールを示します(これは実際の実装であり、ECMA標準ではありません)これを理解するための試みを、主にラバーダッキングの方法として書き留めていますが、間違えた場合私の論理では、少なくともここの誰かが私に悲しみを引き起こす前にそれを捕まえることができるでしょう。
- ルール1:ロードとストア間のデータ依存性が侵害されることはありません。
- ルール2:すべてのストアにはリリースセマンティクスがあります。つまり、ロードまたはストアが1つ後に移動することはありません。
- ルール3:すべての揮発性ロードは取得されます。つまり、ロードまたはストアが1つ前に移動することはできません。
- ルール4:ロードとストアがフルバリアを超えることはできません(例:Thread.MemoryBarrier、lockacquire、Interlocked.Exchange、Interlocked.CompareExchangeなど)。
- ルール5:ヒープへのロードとストアは導入されない場合があります。
- ルール6:ロードとストアは、同じ場所から/に隣接するロードとストアを合体する場合にのみ削除できます。
私はこれらのルールを理解しようとしています。
x = y
y = 0 // Cannot move before the previous line according to Rule 1.
x = y
z = 0
// equates to this sequence of loads and stores before possible re-ordering
load y
store x
load 0
store z
これを見ると、ロード0はロードyの前に移動できるように見えますが、ストアはまったく再注文されない可能性があります。したがって、スレッドがz == 0を認識している場合、x==yも認識します。
yが揮発性の場合、負荷0は負荷yの前に移動できません。そうでない場合は移動できます。揮発性の店舗には特別な特性はないようです。店舗を相互に再注文することはできません(これは非常に強力な保証です!)
完全な障壁は、砂の中の線のようなもので、積み込みや保管を移動することはできません。
ルール5が何を意味するのかわかりません。
ルール6は、次のことを意味すると思います。
x = y
x = z
次に、CLRがyへのロードとxへの最初のストアの両方を削除することができます。
x = y
z = y
// equates to this sequence of loads and stores before possible re-ordering
load y
store x
load y
store z
// could be re-ordered like this
load y
load y
store x
store z
// rule 6 applied means this is possible?
load y
store x // but don't pop y from stack (or first duplicate item on top of stack)
store z
yが揮発性だった場合はどうなりますか?上記の最適化の実行を禁止するルールはありません。2つの同一条件間のlock()により、負荷が隣接する位置に移動するのを防ぐため、これはダブルチェックロックに違反しません。ルール6によれば、負荷を排除できるのはこのときだけです。
ですから、ここではルール5以外はすべて理解していると思います。誰かが私を啓発したい(または私を訂正するか、上記のいずれかに何かを追加したいですか?)