C# C“是”;易挥发;真的需要作为关键词吗?

C# C“是”;易挥发;真的需要作为关键词吗?,c#,.net,multithreading,jit,volatile,C#,.net,Multithreading,Jit,Volatile,当我越来越深入地阅读volatile关键字的含义时,我一直在对自己说“这是实现的方式,不应该成为高级编程语言的一部分”。 我的意思是,CPU缓存数据这一事实应该是JIT编译器感兴趣的,而不是C#程序员感兴趣的 一个重要的选择可能是属性(比如,VolatileAttribute) P> > I/IIrc,C++中的易失性主要是内存映射I/O而不是缓存。如果你读同一个端口两遍,你会得到不同的答案。尽管如此,我还是同意你的评估,即这在C#中作为一个属性更清晰地表达出来 另一方面,在C#中volati

当我越来越深入地阅读
volatile
关键字的含义时,我一直在对自己说“这是实现的方式,不应该成为高级编程语言的一部分”。
我的意思是,CPU缓存数据这一事实应该是JIT编译器感兴趣的,而不是C#程序员感兴趣的

一个重要的选择可能是属性(比如,
VolatileAttribute


<> P> > I/IIrc,C++中的易失性主要是内存映射I/O而不是缓存。如果你读同一个端口两遍,你会得到不同的答案。尽管如此,我还是同意你的评估,即这在C#中作为一个属性更清晰地表达出来

另一方面,在C#中volatile的大多数实际用法可以更好地理解为线程锁,因此选择volatile可能有点不幸


编辑:只需添加:两个链接,以显示在C/C++`volatile用于多线程。

如果使用属性,则可以接受,反之亦然,也就是说,编译器将假定所有变量都是volatile的,除非显式地用属性标记为安全的。这将对性能产生难以置信的影响

因此,我们假设,由于在编译器的视图之外更改变量的值是一种简化操作,因此编译器会假设它不会发生

然而,这可能发生在程序中,因此语言本身必须有一种方式来显示这一点


此外,您似乎对“实现细节”感到困惑。这个术语指的是编译器在你背后做的事情。这里的情况并非如此。您的代码正在编译器视图之外修改变量。因为它在你的代码中,所以它总是正确的。因此,langauge必须能够指出这一点。

我认为你被误导了。所有关于缓存等技术的东西都是试图用低级术语解释它的一部分。volatile的功能描述是“我可能被共享”。鉴于默认情况下线程之间不能共享任何内容,这并不奇怪。我认为这是一个基本问题,足以证明关键字优于属性,但我认为它很大程度上受到历史决策的影响(C++)


替换/优化它的一种方法是使用volatireRead()和volatireWrite()调用。但这更像是“实施”

嗯,我当然同意,这样一个实现细节被暴露出来是非常可怕的。但是,它与lock关键字公开的细节完全相同。我们离这个bug生成器还有很长的路要走,要从我们的代码中完全删除它

硬件人员有很多工作要做。volatile关键字对具有弱内存模型的许多CPU核心很重要。市场对他们并不友好,Alpha和安腾的表现也不好。不太清楚原因,但我怀疑为这些核心编写实心线程代码的困难与此有很大关系。出错是调试的噩梦。volatile的MSDN库文档中的措辞适用于这类处理器,否则它对于x86/x64内核是非常不合适的,并且听起来关键字的作用远远超过了它的实际作用。Volatile仅仅防止变量值存储在这些核心上的CPU寄存器中

不幸的是,在某些特定环境下,x86内核上的volatile仍然很重要。我还没有发现任何证据表明它对x64内核很重要。据我所知,由SSCLI20中的源代码支持的Opcodes.Volatile指令对于x64抖动来说是不可操作的,既不改变编译器状态也不发出任何机器代码。这是正确的方向

一般的建议是,无论您在哪里考虑volatile,都应该首先考虑使用lock或某个同步类。避免他们尝试优化代码是一种微观优化,当程序出现线程竞争问题时,你将失去大量睡眠。c#中的volatile发出了正确的屏障或围栏,这对从事多线程工作的程序员来说很重要。请记住,编译器、运行时和处理器都可以在一定程度上对读/写进行重新排序(每个都有自己的规则)。尽管CLR 2.0具有CLI ECMA指定的更强的内存模型,但CLR内存模型仍然不是最严格的内存模型,因此您需要C#中的
volatile


作为一个属性,我认为不能在方法体中使用属性,因此关键字是必需的。

+1我认为在这种情况下VolatileAttribute是可以的。但是我不知道为什么MS会变成关键字。C的假设应该类似C++,C++已经有了<代码>易失性< /代码>。既然他们决定需要这个功能(我同意),关键字已经在“相似”的集合中,为什么不直接使用它呢?”Blindy:C++的易失性有不同的使用模式,所以我会保持它的清晰,这并没有什么不同,语义上它们实际上是非常相似的,并且它已经存在了。为什么要使事情过于复杂?@Blindy:因为在C/C++中,“volatile”用于多线程。但这只是我的观点。Thread.volatireRead和Thread.volatireWrite方法禁止调用Thread.MemoryBarrier。如果volatile关键字是no-op,这意味着volatile关键字的工作方式不同于volatieread和VolatileWrite方法。哎呀!(不,Thread.MemoryBarrier最好不要是no-op。x86和x64 CPU具有存储缓冲区,这会导致存储区的重新排序,然后是加载。存储区之后是加载是Dekker的核心,因此如果不使用内存屏障,Dekker会在这些ARCH上中断。好的资源是)它们不包括屏障,钛比这更变化无常。刷新挂起的读取和写入是分开的。那里w