【发布时间】:2017-01-31 10:56:01
【问题描述】:
我有一个锯齿状的double[][] 数组,可以由多个线程同时修改。我想让它成为线程安全的,但如果可能的话,没有锁。线程很可能针对数组中的相同元素,这就是出现整个问题的原因。我找到了使用Interlocked.CompareExchange 方法以原子方式递增双精度值的代码:Why is there no overload of Interlocked.Add that accepts Doubles as parameters?
我的问题是:如果Interlocked.CompareExchange 中存在锯齿状数组引用,它会保持原子性吗?非常感谢您的见解。
举个例子:
public class Example
{
double[][] items;
public void AddToItem(int i, int j, double addendum)
{
double newCurrentValue = items[i][j];
double currentValue;
double newValue;
SpinWait spin = new SpinWait();
while (true) {
currentValue = newCurrentValue;
newValue = currentValue + addendum;
// This is the step of which I am uncertain:
newCurrentValue = Interlocked.CompareExchange(ref items[i][j], newValue, currentValue);
if (newCurrentValue == currentValue) break;
spin.SpinOnce();
}
}
}
【问题讨论】:
-
就我个人而言,我会将
newCurrentValue重命名为oldValue- 这只是令人困惑 :) -
您是否意识到 while() 与使用 SpinLock 基本相同,但增加了复杂性?
-
@Gusman 您确实需要循环 - 在(罕见的)碰撞情况下您需要从头开始重做
-
@MarcGravell 用他的代码,是的,但问题的关键是避免锁,最后的循环与自旋锁相同,所以使用提供的机制并不是更好而不是自己滚动?
-
@Gusman 我能看到的代码中唯一的循环是“重复直到成功”循环,它是必需的,与旋转无关;我错过了什么吗?
标签: c# arrays multithreading concurrency interlocked