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

假设有两个线程竞相执行此方法,并且第一个线程立即成功执行,而第二个线程最初不做任何更改,必须重申。没有其他竞争者,第二个线程是否有可能在第二次尝试中失败

如果示例的第二个线程在第二次尝试上无法失败,那么使用spinwait会得到什么?如果不太可能发生一百个线程争分夺秒地执行该方法的情况,可以缩短几个周期?

ckm5138 回答:基于CompareExchange的互锁实施是否应该使用SpinWait?

我的非专家意见是,在这种特殊情况下,如果两个线程偶尔调用AddIfLessThan,则不需要SpinWait。如果两个线程都在一个紧密的循环中调用AddIfLessThan可能会很有用,这样每个线程都可以使进程在不中断的情况下持续几微秒。

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

,

两个线程不是SpinWait讨论的主题。但是这段代码并没有告诉我们实际上有多少线程可以争用资源,并且在线程数量相对较多的情况下,使用SpinWait可能会有所帮助。尤其是在线程数量较多的情况下,试图成功获取资源的虚拟线程队列会变得更长,并且恰好在最后被服务的那些线程很有可能超过调度程序分配的时间片,这反过来又可以导致更高的CPU使用率,并且即使优先级更高,也可能影响其他调度线程的执行。 SpinWait通过设置允许旋转的上限来解决此问题,此后将执行上下文切换。因此,在为了触发上下文切换而进行昂贵的系统调用的必要性与在某些情况下可能影响其他线程执行的风险的不受控制的用户模式CPU消耗之间进行合理的权衡。

本文链接:https://www.f2er.com/3165746.html

大家都在问