5

例:

Thread a:  Interlocked.Increment(ref x);

Thread b:  int currentValue = x;

スレッド a の後にスレッド b が実行されると仮定すると、スレッド b の「currentValue」はインクリメントされた値であることが保証されますか? または、スレッド b は Thread.VolatileRead(ref x) を実行する必要がありますか?

4

2 に答える 2

5

技術的には、.NET が実行されている CPU によって異なりますが、一般的な CPU の場合、答えはイエスです。Interlocked.Increment に対してキャッシュの一貫性が保証されます。これは、MESI の要求に応じてメモリ バリアとして機能します。

CPU はキャッシュ内に無効な行を持つことができますが、その行が無効であることをまだ認識していません。無効化キューには、まだ処理されていない無効化が含まれています。(無効化キューはキャッシュの反対側にあります。CPU はストア バッファと同様にスキャンできません)。その結果、メモリバリアが必要になります。

http://en.wikipedia.org/wiki/MESI_protocol (x86)

MOESI (AMD64 チップで使用) は非常に似ています。

http://en.wikipedia.org/wiki/MOESI_protocol (AMD64)

于 2012-12-12T23:39:46.427 に答える
3

私が理解しているように、Interlocked は、他の Interlocked メソッドによってアクセスされた場合にのみ保証されます。これは、アトミックであることを保証できない x86 システムで 64 ビット値について話す場合に特に重要になる可能性があるため、破損した値が懸念されます。Interlocked によって変更できる値を確実に読み取るための優れたトリックは、CompareExchange です。

int val = Interlocked.CompareExchange(ref field, 0, 0);

これは の値fieldを 0 に変更しますが、古い値が 0 の場合のみ - それ以外の場合は何もしません。いずれにせよ、古い値が返されます。つまり、基本的には、値を変更せずに読み取り、他のインターロック メソッドに対して安全です。

于 2012-12-12T23:54:46.513 に答える