其他人已经解决了“为什么?”。Add(ref double, double)
然而,使用原语很容易滚动你自己的CompareExchange
:
public static double Add(ref double location1, double value)
{
double newCurrentValue = location1; // non-volatile read, so may be stale
while (true)
{
double currentValue = newCurrentValue;
double newValue = currentValue + value;
newCurrentValue = Interlocked.CompareExchange(ref location1, newValue, currentValue);
if (newCurrentValue == currentValue)
return newValue;
}
}
CompareExchange
如果当前值等于 ,则将 的值设置location1
为。由于它以原子的、线程安全的方式执行,我们可以单独依赖它而无需求助于锁。newValue
currentValue
为什么是while (true)
循环?在实现乐观并发算法时,这样的循环是标准的。如果当前值与 不同,CompareExchange
则不会改变。我初始化为- 进行非易失性读取(这可能是陈旧的,但这不会改变正确性,因为将检查值)。如果当前值(仍然)是我们从 中读取的值,则将值更改为。如果没有,我们必须使用新的当前值重试,如.location1
currentValue
currentValue
location1
CompareExchange
location
CompareExchange
newValue
CompareExchange
CompareExchange
If the value is changed by another thread until the time of our next CompareExchange
again, it will fail again, necessitating another retry - and this can in theory go on forever, hence the loop. Unless you are constantly changing the value from multiple threads, CompareExchange
will most likely be called only once, if the current value is still what the non-volatile read of location1
yielded, or twice, if it was different.