3

答えを見つけることができなかったいくつかの簡単な (できれば) 質問があります -

複数のスレッドにアクセスできるオブジェクト a、b があるとします。

Interlocked.Exchange(ref a, b)

「b」が揮発性でない場合、この操作はそれをそのように扱いますか? つまり、この変数の最新の値をメモリから取得しますか? もしそうなら、それは書き込みで「アトミック」に読み取られますか?Interlocked.Exchange の主な目的は、新しい書き込みによるアトミック操作として以前の値 'a' を取得することであることを理解しています。しかし、私の主な混乱は、「b」の値が実際に「a」に書き込まれることです。

私の 2 番目の質問は、この記事の引用に関連しています。

http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/

「興味深い点の 1 つは、C# でのすべての書き込みは、こことここで文書化されているメモリ モデルに従って揮発性であり、おそらくそのように実装されていることです。C# 言語の ECMA 仕様は、実際にはデフォルトで書き込みが揮発性ではない、より弱いモデルを定義しています。 ."

これは本当ですか?もしそうなら、「a」の以前の値を気にしない場合、Interlocked.Exchange の目的はありますか? (私の最初の例に関係する)。すべての書き込みが揮発性であることについて、StackOverflow に関する他の記事やコメントは見当たりません。ただし、書き込みはアトミックであることは理解しています。

編集:私の最初の質問への答えが「b」は揮発性として扱われないということであり、2番目の質問への答えが書き込みが実際に揮発性であるということである場合、フォローアップは、interlocked.exhangeが有用な場合はいつですか? 「a」の以前の値は気にしませんか?

4

3 に答える 3

7

渡された変数Exchange(または任意のメソッドに渡された任意の揮発性変数)は、渡されたときに「揮発性」を保持しません...実行するのは次のvolatileことだけなので、実際には(メソッド呼び出しの期間中)必要はありvolatileません。コンパイラが変数の使用を最適化しないようにしてください(これは通常、レジスタへの書き込みを最適化して、値が単一のプロセッサでのみ「認識」できるようにすることを意味します)。x86 / x64以外のプロセッサでは、これは、取得または解放のセマンティクスを保証する命令を意味する場合があります。.NETは引数の受け渡しにレジスターを使用しないため、volatileは渡される引数の「揮発性」に影響を与えることができませんでした。メモリモデルの可視性が保証されているため、常にメモリから最新の値を取得する必要があります

RE質問2:引用は「一種の」真であり、フィールドの宣言に応じて、フィールドの可視性が保証されます。ただし、「揮発性」フィールドアクセスがない場合、使用の特定のフェーズでレジスタに最適化でき、他のプロセッサからの特定の書き込みを隠す可能性があります。

Interlocked交換により、アトミックではなかった操作がアトミックに見えます。本来の交換は次のようなものです。

var x = someVariable;
someVariable = y;

のタイプに関係なく、これをアトミックにすることはできませんsomeVariableExchangeこの操作をアトミックにします。doubleこれもアトミックで、、long(32ビット)などの非アトミックタイプです。

このアトミックを作成するために行うことの一部は、Exchangeメモリフェンスを使用することです。これにより、書き込みが表示され、メモリフェンスの後の一連の命令で同じメモリアドレスの読み取りで並べ替えられなくなります。

Exchange以前の「a」の値を気にしないのに、なぜ使用するのでしょうか。実際の「交換」を気にしない場合は、VolatileWriteより適切なようです。

または、「交換」が必要ない場合は、次のようにモデル「A=B」にスレッドセーフなコードを記述できます。

Thread.MemoryBarrier();
A=B;

FWIWInterlockedは、一部のプロセッサのコンペアアンドスワップ(CAS)命令を中心に部分的にモデル化されています。これらの命令により、これら2つの操作を1つの命令で実行できます(アトミックにします)。このようなことがなければInterlocked、コンパイラがこれらのCAS命令の1つを使用する必要があると推測するのは難しいかもしれません。さらに、InterlockedこれらのCAS命令(およびincやdecなどの他の潜在的に非アトミックな命令-すべてのプロセッサで使用できるとは限らない)をサポートしないプロセッサでのアトミックな使用法を提供します

于 2012-10-22T14:46:56.857 に答える
1

「b」が揮発性でない場合、この操作はそれをそのように扱いますか?

はい、このソースによると、クラスのすべてのメソッドがInterlocked暗黙的なメモリ フェンスを生成するためです。

于 2012-10-22T14:37:58.187 に答える
1

「b」が揮発性でない場合、この操作はそれをそのように扱いますか?

bが共有変数である場合、これを使用するべきではないと思います。それで、問題全体が解消されます。しかし、Exchange は常にメモリバリアを使用するため、答えはおそらく「はい」です。

「a」の以前の値を気にしない場合、interlocked.exhange が役立つのはいつですか?

へのオーバーロードは、それ以外の場合はアトミックではないdoubleため、非常に便利です。double32 ビット システムの Int64 についても同様です。

しかし、Exchange()アトミック型のオーバーロードのユース ケースはあまり明確ではありません。ほとんどのアルゴリズムはCompareExcange().

したがって、それをアトミックな Write() と考えてください。

于 2012-10-22T14:36:07.990 に答える