以下是基于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会使两个线程仅比单个线程慢一点。

07-27 21:22