为什么不在System.Double和System.Long上使用volatile?

时间:2011-01-18 17:27:36

标签: c# .net multithreading volatile

像我这样的问题一直是asked,但我的有点不同。问题是,“为什么C#类型System.DoubleSystem.Int64等不允许使用volatile关键字?”

乍一看,我回答了我的同事,“好吧,在32位机器上,这些类型至少需要两个滴答才能进入处理器,.Net框架的目的是抽象出特定于处理器的细节。像那样。”他回答说:“如果由于处理器特定的问题导致你无法使用某个功能,那么它就不会抽象出任何东西!”

他暗示特定于处理器的细节不应该出现在使用框架的人身上,该框架“抽象”远离程序员的细节。因此,框架(或C#)应该抽象出那些并做它需要做的事情来为System.Double等提供相同的保证(无论是信号量,内存障碍还是其他)。我认为框架不应该在volatile上添加信号量的开销,因为程序员不期望使用这样的关键字这样的开销,因为32位类型不需要信号量。 64位类型的更大开销可能会让人感到意外,因此,更好的.Net框架只是不允许它,并且如果开销是可接受的,那么就可以在更大的类型上使用自己的信号量。

这导致我们调查volatile关键字的全部内容。 (见this页面)。该页面在注释中说明:

  

在C#中,在字段上使用volatile修饰符可确保对该字段的所有访问都使用VolatileRead或VolatileWrite。

嗯..... VolatileReadVolatileWrite都支持我们的64位类型!!那么,我的问题是,

  

“为什么类型C#System.DoubleSystem.Int64中不允许使用volatile关键字?”

4 个答案:

答案 0 :(得分:17)

  

他暗示特定于处理器的细节不应该出现在使用框架的人身上,该框架“抽象”远离程序员的细节。

如果您使用低锁技术(如易失性字段,显式内存屏障等),那么您在处理器特定细节的世界中完全。为了编写使用低锁技术的正确,可移植,强大的程序,您需要在深层精确地理解处理器是什么,并且不允许执行重新排序,一致性等等。

此功能的目的是说“我正在放弃单线程编程所保证的方便抽象,并通过深入了解我的处理器实现知识来获得性能提升。”当你开始使用低锁技术时,你应该期待更少的抽象,而不是更多的抽象

你大概是因为某种原因而“走向金属”;你支付的价格是必须处理所述金属的怪癖。

答案 1 :(得分:12)

是。原因是您甚至无法在一次操作中阅读doublelong。我同意这是一个糟糕的抽象。我有一种感觉,理由是以原子方式阅读它们需要付出努力,而且对于编译器来说它会非常聪明。因此,他们会让您选择最佳解决方案:lock ing,Interlocked

有趣的是,它们实际上可以使用MMX寄存器在32位上原子读取。这就是Java JIT编译器的功能。它们可以在64位机器上原子读取。所以我认为这是设计上的严重缺陷。

答案 2 :(得分:5)

不是你问题的答案,但......

我非常确定您引用的MSDN文档在声明“使用字段上的volatile修饰符时保证对该字段的所有访问都使用VolatileRead或VolatileWrite”时是错误的。

直接读取或写入volatile字段只会产生半栅栏(读取时为获取栅栏,写入时为释放栅栏)。

VolatileReadVolatileWrite方法在内部使用MemoryBarrier,这会产生全屏障。

Joe Duffy对并发编程知之甚少; this is what he has to say about volatile

  

(顺便说一下,很多人都在想   负载和负载之间的差异   变量存储标记为volatile   并调用Thread.VolatileRead和   Thread.VolatileWrite。区别   是以前的API是   实施强于jitted   代码:他们实现获取/发布   通过发射完整围栏的语义   右边。 API更多   打电话也很贵,但至少   让你决定一个   以呼叫站点为基础的   个人装货和商店需要   MM保证。)

答案 3 :(得分:3)

这是遗产的简单解释。如果您阅读本文 - http://msdn.microsoft.com/en-au/magazine/cc163715.aspx,您会发现.NET Framework 1.x运行时的唯一实现是在x86计算机上,因此Microsoft有必要针对x86内存模型实现它。稍后添加了x64和IA64。所以基本内存模型总是x86之一。

它可以用于x86吗?我实际上不确定它是否可以完全实现 - 从本机代码返回的double的ref可以对齐到4个字节而不是8个。在这种情况下,所有原子读/写的保证都不再成立。