以下是基于Interlocked.CompareExchange
的互锁方法的实现。
建议此代码在重复之前使用SpinWait
自旋吗?
public static bool AddIfLessThan(ref int location, int value, int comparison)
{
int currentValue;
do
{
currentValue = location; // Read the current value
if (currentValue >= comparison) return false; // If "less than comparison" is NOT satisfied, return false
}
// Set to currentValue+value, iff still on currentValue; reiterate if not assigned
while (Interlocked.CompareExchange(ref location, currentValue + value, currentValue) != currentValue);
return true; // Assigned, so return true
}
我已经看到
SpinWait
在这种情况下使用,但是我的理论是应该没有必要。毕竟,循环仅包含少量指令,并且总是有一个线程在进行。假设有两个线程竞相执行此方法,并且第一个线程立即成功执行,而第二个线程最初不做任何更改,必须重申。没有其他竞争者,第二个线程是否有可能在第二次尝试时失败?
如果示例的第二个线程在第二次尝试中不能失败,那么使用
SpinWait
可以得到什么?如果不太可能发生一百个线程争分夺秒地执行该方法的情况,可以省去几个周期吗? 最佳答案
我的非专家意见是,在这种特殊情况下,两个线程偶尔会调用AddIfLessThan
,则不需要SpinWait
。如果两个线程都在一个紧密的循环中调用AddIfLessThan
,这样每个线程都可以使进程不中断几微秒,这可能是有益的。
实际上,我做了一个实验,并测量了一个紧密循环中调用AddIfLessThan
的线程与两个线程的性能。这两个线程需要几乎四倍多的次数才能进行相同数量的循环(累积)。在混合物中添加SpinWait
会使两个线程仅比单个线程慢一点。