首页 > 解决方案 > 基于 CompareExchange 的联锁实现是否应该使用 SpinWait?

问题描述

下面是一个基于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在这种情况下使用过,但我的理论是它应该是不必要的。毕竟,循环只包含少量指令,并且总是有一个线程在进行。

假设两个线程竞相执行此方法,第一个线程立即成功,而第二个线程最初没有更改,必须重复。在没有其他竞争者的情况下,第二个线程是否有可能在第二次尝试时失败

如果示例的第二个线程在第二次尝试时不能失败,那么我们可以通过 a 获得SpinWait什么?万一有一百个线程竞相执行该方法,是否可以缩短几个周期?

标签: c#multithreadingcompare-and-swapinterlockedspinwait

解决方案


我的非专家意见是,在这种特殊情况下,两个线程偶尔调用AddIfLessThanaSpinWait是不需要的。如果两个线程都AddIfLessThan在一个紧密的循环中调用,这可能是有益的,这样每个线程都可以在几微秒内不间断地进行进程。

实际上,我做了一个实验,并测量了一个线程AddIfLessThan在紧密循环中调用与两个线程的性能。这两个线程需要几乎四倍的时间才能进行相同数量的循环(累积)。将 a 添加SpinWait到混合中会使两个线程仅比单个线程慢一点。


推荐阅读