并发修改double[][]元素不加锁

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)

Mar*_*ell 5

是的,它仍然是原子的和线程安全的。对同一单元格的任何调用都会将相同的地址传递给双精度值。诸如它是否在对象上的作为字段的数组中的详细信息是无关紧要的。

但是,该行:

double newCurrentValue = items[i][j];
Run Code Online (Sandbox Code Playgroud)

不是原子的 -理论上可以给出一个撕裂的值(特别是在 x86 上)。在这种情况下这实际上是可以的,因为在撕裂值场景中,它只会命中循环,算作碰撞,然后重做 - 这次使用来自CompareExchange.