`volatile`在线程之间同步变量

Bar*_*uch 7 c c++ multithreading volatile

我有一个int foo从两个线程访问的变量.假设我没有竞争条件问题(访问受到互斥锁的保护,所有操作都是原子的,或者其它任何方法都可以防止竞争条件),仍然存在"寄存器缓存"的问题(缺少更好的名称) ,编译器可能会认为如果变量被读取两次而没有在两者之间写入,则它是相同的值,因此可以"优化"诸如以下内容:

while(foo) { // <-may be optimized to if(foo) while(1)
  do-something-that-doesn't-involve-foo;
}
Run Code Online (Sandbox Code Playgroud)

要么

if(foo) // becomes something like (my assembly is very rusty): mov ebx, [foo]; cmp ebx, 0; jz label;
  do-something-that-doesn't-involve-foo;
do-something-else-that-doesn't-involve-foo;
if(foo) // <-may be optimized to jz label2;
  do-something;
Run Code Online (Sandbox Code Playgroud)

并标记foovolatile解决这个问题?是否保证一个线程的更改到达另一个线程?

如果没有,还有什么方法可以做到这一点?我需要一个Linux/Windows解决方案(可能是单独的解决方案),没有C++ 11.

Mas*_*Man 11

你需要的是记忆障碍.

MemoryBarrier();
Run Code Online (Sandbox Code Playgroud)

要么

__sync_synchronize();
Run Code Online (Sandbox Code Playgroud)

编辑:我加粗了有趣的部分,这里是维基文章的链接(http://en.wikipedia.org/wiki/Memory_barrier#cite_note-1)和相关的参考文献(http://www.rdrop.com) /users/paulmck/scalability/paper/whymb.2010.07.23a.pdf)

这是你的另一个问题的答案(来自维基百科):在C和C++中,volatile关键字旨在允许C和C++程序直接访问内存映射的I/O. 内存映射I/O通常要求源代码中指定的读取和写入按照指定的确切顺序发生,没有任何遗漏.编译器的读取和写入的遗漏或重新排序将破坏程序与内存映射I/O访问的设备之间的通信.AC或C++编译器可能无法对易失性存储器位置进行读取和写入,也不会省略对易失性存储器位置的读取或写入.关键字volatile不保证内存屏障可以强制执行缓存一致性.因此,单独使用"volatile"不足以在所有系统和处理器上使用变量进行线程间通信[1]

检查一下,它提供了很好的解释:http : //channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2


R..*_*R.. 9

如果访问受互斥锁保护,则无需担心任何问题.这里的volatile关键字没用.互斥锁是一个完整的内存屏障,因此不能通过互斥锁或解锁调用缓存其地址可以在外部可见的对象.