Microsoft特定
当使用/ volatile:ms编译器选项时 - 默认情况下 ARM以外的体系结构是目标 - 编译器生成额外的 用于维护对volatile中的volatile对象的引用的排序的代码 除了维持对其他全局的引用的排序 对象。特别是:
- 对volatile对象的写入(也称为volatile write)具有Release语义;也就是说,对全局或静态对象的引用
在写入指令中的易失性对象之前发生的 序列将在编译后的volatile写入之前发生 二进制。- 读取volatile对象(也称为volatile read)具有Acquire语义;也就是说,对全局或静态对象的引用
在指令中读取易失性存储器后发生的情况 序列将在编译二进制文件中的volatile读取之后发生。这使得volatile对象可用于内存锁定和释放 在多线程应用程序中。
它确实保证volatile
阻止编译器执行编译时指令重新排序(因为它明确指出该指令
序列将与编译二进制文件中的相同。)
但是众所周知,还有像硬件重新排序这样的东西(比如CPU可以自己重新排序指令)。 volatile
也会阻止它吗?我知道同步原语(例如互斥体)可以,但MS特定的volatile
呢?
答案 0 :(得分:7)
关于MS特定的易失性行为的MSDN文档会一直回到VS2003。所以它在C ++ 11中存在std::atomic
之前已经存在了很长一段时间。
因此,MS特定的volatile似乎是过去获得/释放语义的方式。但现在它基本上已经过时了,他们留下了一个脚注,让你远离MS-volatile而支持std::atomic
和/volatile:iso
进行线程间通信。
至于他们为何排除ARM,微软直到最近才开始接收ARM。除了ARM之外,它们还支持x86,x64和Itanium(已经死了)。
在x86和x64上,大多数加载和存储已经具有获取/释放语义(例如非临时存储等)。因此,只要编译器不对任何内容重新排序,处理器就不会 * ,因此将保留获取/释放语义。 /volatile:ms
标志告诉编译器不要重新排序任何内容,以便可以在x86和x64上实现获取/释放语义。
由于Microsoft的ARM支持相对较新,并且MS特定的volatile(/volatile:ms
)已过时而支持std::atomic
,因此他们可能决定放弃经典的volatile语义而不是更新它们来处理ARM也是如此(由于缺乏硬件支持,这可能意味着在任何地方增加内存屏障)。
*处理器仍将执行它想要的任何重新排序,但它将保留程序的获取/释放语义,因为x86 / x64需要它。 (减去像nt-stores或clflush这样的特殊情况)如何在不违反内存排序的情况下执行此操作是另一个主题。