任意の値によるインクリメントをサポートするスレッドセーフなカウンターの実装を探していたInterlocked
ところ、ドキュメントから直接このサンプルを見つけましたInterlocked.CompareExchange
(簡単にするためにわずかに変更されています)。
private int totalValue = 0;
public int AddToTotal(int addend)
{
int initialValue, computedValue;
do
{
// How can we get away with not using a volatile read of totalValue here?
// Shouldn't we use CompareExchange(ref TotalValue, 0, 0)
// or Thread.VolatileRead
// or declare totalValue to be volatile?
initialValue = totalValue;
computedValue = initialValue + addend;
} while (initialValue != Interlocked.CompareExchange(
ref totalValue, computedValue, initialValue));
return computedValue;
}
public int Total
{
// This looks *really* dodgy too, but isn't
// the target of my question.
get { return totalValue; }
}
このコードが何をしようとしているのかはわかりますが、追加された一時変数に代入するときに、共有変数の揮発性読み取りを使用しないことでどのように回避できるかわかりません。
initialValue
ループ全体で古い値を保持し、関数が返されない可能性はありますか? それとも、メモリバリア (?)CompareExchange
によってそのような可能性は排除されますか? 任意の洞察をいただければ幸いです。
編集CompareExchange
:の後続の読み取りが最後の呼び出しtotalValue
の時点で最新である場合、このコードは問題ないことを理解していることを明確にする必要があります。しかし、それは保証されていますか? CompareExchange