Interlocked.Exchange和Volatile.Write之间的区别?

时间:2012-09-14 13:37:39

标签: c# .net-4.5

Interlocked.Exchange和Volatile.Write有什么区别?

两种方法都会更新某些变量的值。有人可以总结何时使用它们吗?

http://msdn.microsoft.com/ru-ru/library/bb337971http://msdn.microsoft.com/en-us/library/gg712713.aspx

特别是我需要更新我的数组的双项,我希望另一个线程看到最新的值。什么是首选? Interlocked.Exchange(ref arr[3], myValue)Volatile.Write(ref arr[3], info);其中arr被声明为double

=============================================== ============================= 真实的例子,我声明像这样的双数组:

private double[] _cachedProduct;

在一个帖子中我更新它:

        _cachedProduct[instrumentId] = calcValue;
        ...
        are.Set();

在另一个线程中我读了这个数组:

        while(true) {
            are.WaitOne();
            ...
                result += _cachedProduct[instrumentId];
            ...
        }

对我而言,它的工作正常。但是,要确保“它始终有效”,无论看起来如何,我都应添加Volatile.WriteInterlocked.Exchange。因为双重更新不能保证是原子http://msdn.microsoft.com/en-us/library/aa691278%28VS.71%29.aspx

在回答这个问题时,我希望看到Volatile和Interlocked类的详细比较。为什么我们需要2节课?哪一个以及何时使用?

1 个答案:

答案 0 :(得分:11)

Interlocked.Exchange使用保证原子操作的处理器指令。

Volatile.Write也是如此,但它还包括一个内存屏障操作。 由于Windows 8上支持ARM处理器,我认为微软在DotNet 4.5上添加了Volatile.Write。英特尔和ARM处理器在内存操作重新排序方面存在差异。

在Intel上,您可以保证内存访问操作的执行顺序与它们的顺序相同,或者至少不会重新排序写操作。

来自英特尔®64和IA-32架构软件开发人员手册,第8章:

  8.2.2 P6及更近期处理器系列中的内存排序英特尔酷睿2双核,英特尔凌动,英特尔酷睿双核,奔腾4和P6系列   处理器还使用处理器排序的内存订购模型   进一步定义为“使用存储缓冲区转发命令写入”。   该模型的特征如下。

在ARM上,您没有这种保证,因此需要内存屏障。可以在此处找到解释此问题的ARM博客:http://blogs.arm.com/software-enablement/594-memory-access-ordering-part-3-memory-access-ordering-in-the-arm-architecture/

在您的示例中,由于不保证使用double的操作是原子操作,我建议使用锁来访问它。请记住,在读取和设置值时,必须对代码的两个部分使用锁定。

更完整的示例会更好地回答您的问题,因为不清楚设置这些值后会发生什么。对于向量,如果您有比读者更多的读者,请考虑使用ReaderWriterLockSlim对象:http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.aspx

线程数和读/写频率可以显着改变锁定策略。