.純記憶モデルに、volatile変数、試験、設定:何を保証しているのでしょうか?
-
21-09-2019 - |
質問
知っている。純記憶モデルできます。NET Framework;いないコンパクト/マイクロ/silverlight/mono/xnaういん)保証される特定の種類、プリミティブ整数を参照)の運営を保証する原子.
さらに、私は、今申し述べたようなx86/x64試験は、セット指示書(および Interlocked.CompareExchange
実際に参考文献のグローバルメモリの場所、そしてそれが成功した際に他の Interlocked.CompareExchange
この新しい値とします。
最後に、私は、今申し述べたような volatile
キーワードが指定できるの コンパイラ 増殖を読み込み&書き込みの早い順序変更に関する業務はこの変数(す).
これまでの数の質問:
- 私の信仰上の正しいのですか。
Interlocked.Read
な過負荷のためにint、long値は2つの言葉にこのような正常に読みに原子的に).私は常に想定されます。純記憶モデルに保証する最新の価値が見られるint値の読み込み時に/を参照しプロセッサーのキャッシュ-登録等私が発表することができないことがあります。であるので、力変数の再取得?- は揮発性を十分にこのような問題点を解決するための整数、参考文献?
- X86/x64きになっているのでしょうか...
これは、私の場合これまでにグローバルの整数変数xとyの両方が0に初期化される場合には書いてい:
x = 1;
y = 2;
このスレッドが参照x=0とy=2のとき(の書き込みが起きています。この変更であれば揮発?
解決
- 最大 32 ビット幅 (x64 システムでは 64 ビット幅) の変数に対する読み取りと書き込みのみがアトミックです。これが意味するのは、あなたは本を読まないということです 整数 そして書きかけの値を取得します。算術がアトミックであるという意味ではありません。
- 連動動作はメモリバリアとしても機能するので、そうです。
Interlocked.CompareExchange
更新された値が表示されます。 - 見る このページ. 。揮発性とは、秩序があることを意味するものではありません。一部のコンパイラは、揮発性変数の操作を再順序付けしないことを選択する場合がありますが、CPU は自由に再順序付けできます。CPU による命令の再順序付けを停止したい場合は、(フル) メモリ バリアを使用します。
- メモリ モデルにより、読み取りと書き込みがアトミックであることが保証され、volatile キーワードを使用すると読み取りが確実に行われます。 いつも レジスタからではなくメモリから取得されます。それであなたは 意思 最新の値を参照してください。これは、x86 CPU が必要に応じてキャッシュを無効にするためです。「」を参照してください。 これ そして これ. 。また、を参照してください。 InterlockedCompareExchange64 64 ビット値をアトミックに読み取る方法については、
- そしていよいよ最後の質問です。答えは、スレッドが実際に見ることができるということです
x = 0
そしてy = 2
, CPU は命令を自由に並べ替えることができるため、volatile キーワードを使用しても状況は変わりません。記憶バリアが必要です。
まとめ:
- コンパイラは命令を自由に並べ替えることができます。
- CPU は命令を自由に並べ替えることができます。
- ワードサイズの読み取りと書き込みはアトミックです。算術演算やその他の操作は、読み取り、計算、書き込みを伴うため、アトミックではありません。
- メモリからのワードサイズの読み取りでは、常に最新の値が取得されます。しかし、ほとんどの場合、実際に記憶を頼りに読んでいるかどうかはわかりません。
- 完全なメモリバリアは (1) と (2) を停止します。ほとんどのコンパイラでは、(1) を単独で停止できます。
- volatile キーワードを使用すると、メモリから読み取っていることが保証されます - (4)。
- インターロックされた操作 (ロック プレフィックス) により、複数の操作をアトミックに行うことができます。たとえば、読み取り + 書き込み (InterlockedExchange)。または、読み取り + 比較 + 書き込み (InterlockedCompareExchange)。これらはメモリバリアとしても機能するため、(1)と(2)は停止されます。これらは常にメモリに書き込むため (当然ですが)、(4) が保証されます。
他のヒント
ったこの古います。の回答からハンスやwj32確一部を除くにつ volatile
.
具体的にはに関するご質問
X86/x64きになっているのでしょうか...の場合 がグローバルの整数変数 xとyの両方が0に初期化される場合 書いてい:
x = 1; y = 2;
このスレッドが参照 x=0とy=2のとき(の書き込みます 起きています。この変更の場合 彼揮発?
の場合 y
は揮発性には、書き込み x
です保証が起こる前に書き込み y
, るため、スレッドが参照 x = 0
や y = 2
.このデータを変更する変数は、"リリースの意味"(論理的に同等の排出のリリースフェンス、すなわちすべての読み書きからの指示で動かなくなパスです。(この場合、xは揮発性がyではないが、予期せぬ x = 0
や y = 2
.) の説明を参照してください&コード例では、 C#仕様 できます。
いいえ、volatileキーワードとアトミック保証はあまりにも弱いです。あなたはそれを保証するために、メモリバリアが必要です。あなたはThread.MemoryBarrier()メソッドを明示的に取得することができます。