Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 联锁.交换和易失性.写入之间的区别?_C#_.net 4.5 - Fatal编程技术网

C# 联锁.交换和易失性.写入之间的区别?

C# 联锁.交换和易失性.写入之间的区别?,c#,.net-4.5,C#,.net 4.5,interlocated.Exchange和Volatile.Write之间有什么区别 这两种方法都会更新某些变量的值。有人能总结一下什么时候使用它们吗 及 特别是我需要更新数组的double项,我希望另一个线程看到最新的值。什么是首选联锁交换(参考arr[3],myValue)或易失性写入(参考arr[3],信息)其中arr声明为double ===========================================================================

interlocated.Exchange和Volatile.Write之间有什么区别

这两种方法都会更新某些变量的值。有人能总结一下什么时候使用它们吗

特别是我需要更新数组的double项,我希望另一个线程看到最新的值。什么是首选<代码>联锁交换(参考arr[3],myValue)或
易失性写入(参考arr[3],信息)其中
arr
声明为
double

============================================================================ 例如,我声明双数组如下:

private double[] _cachedProduct;
        _cachedProduct[instrumentId] = calcValue;
        ...
        are.Set();
        while(true) {
            are.WaitOne();
            ...
                result += _cachedProduct[instrumentId];
            ...
        }
在一个线程中,我将其更新为:

private double[] _cachedProduct;
        _cachedProduct[instrumentId] = calcValue;
        ...
        are.Set();
        while(true) {
            are.WaitOne();
            ...
                result += _cachedProduct[instrumentId];
            ...
        }
在另一个线程中,我这样读取此数组:

private double[] _cachedProduct;
        _cachedProduct[instrumentId] = calcValue;
        ...
        are.Set();
        while(true) {
            are.WaitOne();
            ...
                result += _cachedProduct[instrumentId];
            ...
        }
对我来说,它只是工作得很好。然而,为了确保“它将始终工作”,无论看起来如何,我都应该添加
Volatile.Write
Interlocked.Exchange
。因为双重更新不能保证是原子的


在回答这个问题时,我想看到Volatile类和Interlocked类的详细比较。为什么我们需要两门课?何时使用哪一个?

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

Volatile.Write执行相同的操作,但它还包括一个内存屏障操作。 我认为微软增加了Volatile.Write-on-dotnet4.5,因为它支持Windows 8上的ARM处理器。英特尔和ARM处理器在内存操作重新排序方面有所不同

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

摘自《英特尔64和IA-32体系结构软件开发人员手册》第8章:

8.2.2 P6及更新处理器系列中的内存排序Intel Core 2 Duo、Intel Atom、Intel Core Duo、奔腾4和P6系列 处理器还使用处理器排序的内存排序模型,该模型可以 进一步定义为“使用存储缓冲区转发进行写排序” 该模型的特点如下

在ARM上,您没有这种保证,因此需要一个内存屏障。ARM博客解释了这一点,可在此处找到:

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

一个更完整的例子更好地回答您的问题,因为不清楚设置这些值后会发生什么。对于向量,如果读者比作者多,请考虑使用RealeWrristRooSLIM对象:


线程的数量和读/写的频率会极大地改变您的锁定策略。

您不能使用Volatile。在这种特定情况下写入:它只接受引用类型,而不接受值类型。如果使用等待句柄,它已经保证另一个线程完全看到最新的值。我不想使用锁,因为一个x64系统的“双重更新”可能是自动的,所以我不想引入不需要的额外延迟。这是非常时间敏感的代码,所以我真的想赢得几微秒的额外时间。所以
Volatile.Write
保证原子性。msdn对此没有任何说明。为什么建议使用
?为什么不使用
Interlock.Exchage
Volatile
?我使用Volatile类的描述作为答案的基础。在这里可以找到一篇关于原子和volatile之间区别的好文章:我检查了C语言定义4.0。在第5.5节中,他们没有更新文档,将double作为原子操作。你问了一个方法来保证它总是工作的,所以锁就是这样的保证。在您的示例的特定情况下,这将取决于在.net中始终依赖CLR的哪个线程增量InstrumentIDrememember,以及Microsoft在执行前如何翻译它。正如你所说,64位机器可以进行原子双运算。但是由微软编写的语言规范明确表示,他们不保证双倍使用。