Windows + VisualC上是否有易失性读写原子?

Mar*_* Ba 11 c++ atomic volatile memory-fences visual-c++

有一对夫妇在这个网站,询问使用是否问题volatile变量原子/多线程访问是可能的:见这里,这里,还是这里的例子.

现在,符合C(++)标准的答案显然没有.

但是,在Windows和Visual C++编译器上,情况似乎并不那么清楚.

我最近回答,并引用了官方的MSDN文档volatile

微软特定

声明为volatile的对象是(...)

  • 对volatile对象的写入(volatile write)具有Release语义; 对全局或静态对象的引用在编译二进制文件中的易失性写入之前,将在写入指令序列中的易失性对象之前发生这种情况.
  • 读取volatile对象(volatile read)具有Acquire语义; 对全局或静态对象的引用 在读取编译二进制文件中的易失性读取之后,将在读取指令序列中的易失性存储器之后发生这种情况.

这允许volatile对象用于多线程应用程序中的内存锁定和释放.

[强调我的]

现在,读到这一点,在我看来,MS编译器将处理一个易变量变量,就像std::atomic即将推出的C++ 11标准一样.

然而,在对我的回答评论中,用户Hans Passant写道:"那篇MSDN文章非常不幸,这是错误的.你不能用volatile来实现锁定,甚至不能使用微软的版本.(...)"


请注意:MSDN中给出的示例看起来很可疑,因为您通常无法在没有原子交换的情况下实现锁定.(正如亚历克斯指出的那样)这仍然留下了问题.有关此MSDN文章中给出的其他信息的有效性,特别是对于此处此处的用例.)


此外,还有Interlocked*函数的文档,尤其是InterlockedExchange带有volatile(!?)变量并进行原子读取和写入.(注意我们在SO上有一个问题 - 何时应该使用InterlockedExchange? - 没有权威性地回答是否需要这个函数来进行只读或只写原子访问.)

更重要的是,volatile上面引用的文档以某种方式暗示"全局或静态对象",我认为"真正的" 获取/释放语义应该适用于所有值.

回到问题

在Windows上,使用Visual C++(2005 - 2010),将声明一个(32位?int?)变量volatile允许原子读取和写入此变量 - 或不?

对我来说特别重要的是,它应该独立于程序运行的处理器或平台而在Windows/VC++上保存(或不保存).(也就是说,无论是在Itanum2上运行的WinXP/32bit还是Windows 2008R2/64bit都有关系?)

请用可验证的信息,链接,测试用例备份您的答案!

jco*_*der 6

是的,它们在windows/vc ++上是原子的(假设你符合对齐要求等或课程)

但是对于锁定,您需要进行原子测试和设置,或者比较和交换instuction或类似的,而不仅仅是原子更新或读取.

否则,没有办法测试锁在一个不可分割的操作中声明它.

编辑:如下所述,无论如何,32位或更低版本的x86上的所有对齐内存访问都是原子的.关键是volatile使得内存访问有序.(感谢您在评论中指出这一点)

  • "假设您满足对齐要求"将使得intel平台中的访问原子化,无论操作系统如何.原子性与波动性无关.VS C++编译器中的额外约束仅影响指令的排序和内存栅栏,以确保编译器和CPU都不会执行特定的指令重新排序.并且不保证在32位平台中对64位int进行原子读/写. (3认同)

归档时间:

查看次数:

4615 次

最近记录:

14 年,10 月 前