Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.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_Multithreading - Fatal编程技术网

C# 确保变量的最新值始终对多处理器系统上的多个线程可见

C# 确保变量的最新值始终对多处理器系统上的多个线程可见,c#,.net,multithreading,C#,.net,Multithreading,我正在使用这样的配置: .NET framework 4.5 Windows Server 2008 R2 HP DL360p Gen8(2*Xeon E5-2640,x64) 我的课程中有这样的领域: protected int HedgeVolume; 我从几个线程访问此字段。我假设由于我有多处理器系统,这个线程可能在不同的处理器上执行 我应该怎么做才能保证在任何时候我使用这个字段时,最新的值是“read”?并确保当我“写入”值时,它立即对所有其他线程可用 我该怎么办 就这样离开球场

我正在使用这样的配置:

  • .NET framework 4.5
  • Windows Server 2008 R2
  • HP DL360p Gen8(2*Xeon E5-2640,x64)
我的课程中有这样的领域:

protected int HedgeVolume;
我从几个线程访问此字段。我假设由于我有多处理器系统,这个线程可能在不同的处理器上执行

我应该怎么做才能保证在任何时候我使用这个字段时,最新的值是“read”?并确保当我“写入”值时,它立即对所有其他线程可用

我该怎么办

  • 就这样离开球场吧
  • 声明它是易变的
  • 使用
    联锁
    类访问字段
  • 使用.NET 4.5
    Volatile.Read
    Volatile.Write
    方法访问字段
  • 使用
    lock

我只需要最简单的方法使我的程序在这个配置上工作,我不需要我的程序在其他计算机、服务器或操作系统上工作。另外,我想要最小的延迟,因此我正在寻找最快的解决方案,该解决方案将始终适用于标准配置(多处理器intel x64、.net 4.5)。

取决于您的操作。对于只读,volatile是最简单的,联锁允许更多的控制。锁是不必要的,因为它比您描述的问题更复杂。不确定Volatile.Read/Write,从未使用过它们。

Volatile
-糟糕,有一些问题(见Joe Duffy的博客)

如果您只需读取值或无条件写入值-请使用
Volatile.read
Volatile.write


如果需要读取并随后写入更新的值,请使用
lock
语法。但是,您可以使用
联锁
类功能在不锁定的情况下实现相同的效果,但这更为复杂(涉及
比较交换
s以确保您正在更新读取值,即自读取操作以来未被修改+如果自读取操作以来修改了值,则重试逻辑).

您的问题缺少一个关键要素。。。该领域数据的完整性有多重要

volatile
为您提供了性能,但如果某个线程当前正在向字段写入更改,则在该更改完成之前,您无法获取该数据,因此您可能会访问过期信息,并可能覆盖另一个线程当前正在做的更改。如果数据是敏感的,您可能会遇到很难跟踪的bug。但是,如果您正在进行非常快速的更新,请在不读取值的情况下覆盖该值,并且不关心偶尔会出现过时(几毫秒)的数据,请尝试使用它

lock
保证一次只能有一个线程访问该字段。您只能将其放在写入字段的方法上,而不使用读取方法。缺点是,它很慢,可能会在另一个线程执行其任务时阻塞该线程。但是,您确信您的数据保持有效


Interlock
存在以保护自己不受调度程序上下文开关的影响。我的意见?不要使用它,除非你确切地知道你为什么要使用它以及如何使用它。它提供了选择,但有了好的选择,问题就大了。它防止在更新变量时进行上下文切换。它可能不会按照你的想法去做,也不会阻止并行线程同时执行它们的任务。

当你开始设计一个并发程序时,你应该按优先顺序考虑这些选项:

1) 隔离:每个线程都有自己的私有数据
2) 不变性:线程可以看到共享状态,但它永远不会改变
3) 可变共享状态:使用锁保护对共享状态的所有访问

如果你达到(3),那么你实际需要多快

获取一个无争用的锁需要10纳秒(10-8秒)的时间——这对于大多数应用程序来说已经足够快了,而且是保证正确性的最简单方法

使用您提到的任何其他选项都会使您进入低锁编程的领域,这是非常难以纠正的


如果您想学习如何编写并发软件,应阅读以下内容:

简介:-阅读大约需要一天时间


圣经:-阅读大约需要一个月的时间

您想要使用的
Volatile.read()

当您在x86上运行时,C#中的所有写操作都相当于
Volatile.Write()
,您只需要在安腾上使用它

Volatile.Read()
将确保您获得最新的副本,而不管最后是哪个线程编写的

这里有一篇精彩的文章

其概要包括:

在某些处理器上,编译器不仅必须避免某些 在对易失性读写进行优化时,还必须使用特殊的 说明书在多核机器上,不同的核具有不同的性能 储藏室。处理器可能不会费心让这些缓存保持一致 默认情况下,可能需要特殊说明才能刷新和刷新 储藏室

希望这是显而易见的,除了需要
volatile
来阻止编译器优化它之外,还有处理器

然而,在C#中,所有的写操作都是易变的(与Java不同), 无论是写入易失性字段还是非易失性字段。 因此,上述情况实际上在C#中从未发生过。易变的书写 更新线程的缓存,然后将整个缓存刷新到主线程 记忆

您不需要
Volatile.Write()
。这里有更具权威性的来源。但是,您可能需要它来停止编译器对其重新排序

因为所有的C#写操作都是易变的,所以可以认为所有的写操作都在进行中 直的