我有一个从两个线程访问的变量 int foo
。假设我没有竞争条件问题(访问受互斥锁保护,所有操作都是原子的,或任何其他防止竞争条件的方法),仍然存在“寄存器缓存”问题(因为缺少更好的名称) ,其中编译器可能假设如果变量被读取两次而不在其间写入,则它是相同的值,因此可能会“优化”掉以下内容:
while(foo) { // <-may be optimized to if(foo) while(1)
do-something-that-doesn't-involve-foo;
}
或
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;
将 foo
标记为 volatile
可以解决这个问题吗?来自一个线程的更改是否保证会到达另一个线程?
如果不行,还有什么方法可以做到这一点?我需要一个适用于 Linux/Windows 的解决方案(可能是单独的解决方案),而不是 C++11。
最佳答案
您需要的是内存屏障。
MemoryBarrier();
或
__sync_synchronize();
编辑:我将有趣的部分加粗了,这里是维基文章的链接 ( 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 访问的设备之间的通信。 C 或 C++ 编译器可能不会重新排序对 volatile 内存位置的读取和写入,也可能会忽略对 volatile 内存位置的读取或写入。 关键字 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
关于c++ - `volatile` 在线程之间同步变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18135116/