该站点上有几个问题询问是否可以使用volatile
变量进行原子/多线程访问:例如,请参见此处、此处或此处。
现在,符合 C(++) 标准的答案显然是no。
但是,在 Windows 和 Visual C++ 编译器上,情况似乎并不那么清楚。
微软特定
声明为 volatile 的对象是 (...)
- 对 volatile 对象的写入(volatile write)具有 Release 语义;对全局或静态对象的引用?在指令序列中写入易失性对象之前发生的事件将发生在已编译二进制文件中的易失性写入之前。
- 对 volatile 对象的读取(volatile read)具有 Acquire 语义;对全局或静态对象的引用 ?在指令序列中读取易失性存储器之后发生的情况将发生在已编译二进制文件中的易失性读取之后。
这允许易失性对象用于多线程应用程序中的内存锁定和释放。
[强调我的]
现在,阅读本文,在我看来,MS 编译器std::atomic
将像在即将到来的 C++11 标准中一样处理 volatile 变量。
然而,在对我的回答的评论中,用户Hans Passant写道:“那篇 MSDN 文章非常不幸,它是大错特错。你不能用 volatile 实现锁,即使是微软的版本也不能。(...)”
请注意:MSDN 中给出的示例看起来很可疑,因为您通常无法在没有 atomic exchange的情况下实现锁。(正如亚历克斯也指出的那样。)这仍然留下了问题。对于这篇 MSDN 文章中给出的其他信息的有效性,尤其是对于像这里和这里这样的用例。)
此外,还有 The Interlocked* 函数的文档,尤其是InterlockedExchange
使用volatile(!?)变量并进行原子读写。(请注意,我们对 SO 提出的一个问题—— 何时应使用 InterlockedExchange? ——并没有权威地回答只读或只写原子访问是否需要此函数。)
更重要的是,volatile
上面引用的文档以某种方式暗示了“全局或静态对象”,我认为“真正的”获取/释放语义应该适用于所有值。
回到问题
在 Windows 上,使用 Visual C++ (2005 - 2010),将声明一个 (32bit?int?) 变量以volatile
允许对该变量进行原子读取和写入 - 或不?
对我来说特别重要的是,这应该在 Windows/VC++ 上保持(或不)独立于程序运行的处理器或平台。(也就是说,在 Itanum2 上运行的是 WinXP/32bit 还是 Windows 2008R2/64bit?)
请用可验证的信息、链接、测试用例来支持您的答案!