5

文档中:

微软特定

当使用 /volatile:ms 编译器选项时(默认情况下,当针对 ARM 以外的体系结构时)编译器生成额外的代码来维护对 volatile 对象的引用之间的顺序,以及维护对其他全局对象的引用的顺序。特别是:

  • 对 volatile 对象的写入(也称为 volatile 写入)具有 Release 语义;也就是说,
    在指令
    序列中写入易失性对象之前发生的对全局或静态对象的引用将发生在已编译
    二进制文件中的易失性写入之前。
  • 对 volatile 对象的读取(也称为 volatile 读取)具有 Acquire 语义;也就是说,
    在指令序列中读取易失性存储器之后发生的对全局或静态对象的引用
    将发生在编译二进制文件中的易失性读取之后。

这使得 volatile 对象可以用于多线程应用程序中的内存锁定和释放。

它肯定会保证volatile防止编译器执行编译时指令重新排序(因为它明确指出指令序列在编译后的二进制文件中是相同的)。

但我们都知道,还有硬件重排序之类的东西(比如 CPU 能够根据自己的意愿重新排序指令)。是否volatile也能阻止它?我知道同步原语(例如互斥锁)可以,但是特定于 MS 的volatile呢?

4

1 回答 1

7

有关 MS 特定的易失性行为的 MSDN 文档可以追溯到 VS2003。所以它已经存在了一段时间——早std::atomic在 C++11 出现之前。

因此,特定于 MS 的 volatile 似乎是过去实现获取/释放语义的方式。但现在它基本上已经过时了,他们留下了一个脚注,让你远离 MS-volatile,转而支持std::atomic线程/volatile:iso间通信。


至于他们为什么排除 ARM,微软直到最近才拿起 ARM。除了 ARM,它们还支持 x86、x64 和 Itanium(已死)。

在 x86 和 x64 上,大多数加载和存储已经具有获取/释放语义(非临时存储等例外)。因此,只要编译器不重新排序任何东西,处理器也不会*并因此保留获取/释放语义。该/volatile:ms标志告诉编译器不要重新排序任何东西,以便可以在 x86 和 x64 上实现获取/释放语义。

由于微软对 ARM 的支持相对较新,而且 MS 特定的 volatile ( /volatile:ms) 已经过时std::atomic,他们可能决定放弃经典的 volatile 语义,而不是更新它们以在 ARM 上工作(这可能意味着到处添加内存屏障,鉴于缺乏硬件支持)。

*处理器仍将执行它想要的任何重新排序,但它将保留程序的获取/释放语义,因为这是 x86/x64 所要求的。(减去 nt-stores 或 clflush 等特殊情况)它如何在不违反内存排序的情况下做到这一点是另一个主题。

于 2016-08-11T19:35:17.757 回答