tet*_*sun 5 c# arrays concurrency multithreading interlocked
我有一个double[][]可能被多个线程同时修改的锯齿状数组。我想让它成为线程安全的,但如果可能的话,不要锁。线程很可能以数组中的相同元素为目标,这就是整个问题出现的原因。我找到了使用该Interlocked.CompareExchange方法原子地增加双精度值的代码:为什么没有接受双精度作为参数的 Interlocked.Add 的重载?
我的问题是:如果 中有锯齿状的数组引用,它会保持原子性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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
是的,它仍然是原子的和线程安全的。对同一单元格的任何调用都会将相同的地址传递给双精度值。诸如它是否在对象上的作为字段的数组中的详细信息是无关紧要的。
但是,该行:
double newCurrentValue = items[i][j];
Run Code Online (Sandbox Code Playgroud)
不是原子的 -理论上可以给出一个撕裂的值(特别是在 x86 上)。在这种情况下这实际上是可以的,因为在撕裂值场景中,它只会命中循环,算作碰撞,然后重做 - 这次使用来自CompareExchange.