c# - 基于 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
什么?万一有一百个线程竞相执行该方法,是否可以缩短几个周期?
解决方案
我的非专家意见是,在这种特殊情况下,两个线程偶尔调用AddIfLessThan
aSpinWait
是不需要的。如果两个线程都AddIfLessThan
在一个紧密的循环中调用,这可能是有益的,这样每个线程都可以在几微秒内不间断地进行进程。
实际上,我做了一个实验,并测量了一个线程AddIfLessThan
在紧密循环中调用与两个线程的性能。这两个线程需要几乎四倍的时间才能进行相同数量的循环(累积)。将 a 添加SpinWait
到混合中会使两个线程仅比单个线程慢一点。
推荐阅读
- regex - 在值出现多次的 json 数据中替换正则表达式的语法
- sql - 表中的 SQL 更新 id 列中具有重复数据的行除外
- c# - C#当泛型类型实现某个类时如何转换类
- .net - 在 VS2010 中使用 winsock 时出错:变量“Winsock2”未声明或从未分配
- django - django allauth 自定义登录,除了电子邮件和密码外,还有其他检查
- python - Python:修复无效的 json 字符串
- tfs - 本地 TFS/Azure DevOps 是否与 okta 集成以实现 SSO?
- button - Flutter:如何使按钮不可见但处于活动状态,以便您只能看到文本?
- flutter - 如何通过在 Flutter 中调用 Future 来加载更多项目并在 Listview 构建器中显示
- javascript - 在 three.js 中加载网格