7

I have a variable int foo that is accessed from two threads. Assuming I have no race-condition issues (access is protected by a mutex, all operations are atomic, or whatever other method to protect from race conditions), there is still the issue of "register caching" (for lack of a better name), where the compiler may assume that if the variable is read twice without being written in between, it is the same value, and so may "optimize" away things like:

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

or

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;

does marking foo as volatile solve this issue? Are changes from one thread guaranteed to reach the other thread?

If not, what other way is there to do this? I need a solution for Linux/Windows (possibly separate solutions), no C++11.

4

3 回答 3

11

你需要的是内存屏障。

MemoryBarrier();

或者

__sync_synchronize();

编辑:我已经将有趣的部分加粗,这里是 wiki 文章的链接 ( 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 不能保证内存屏障来强制缓存一致性。因此,仅使用“易失性”不足以在所有系统和处理器上使用变量进行线程间通信[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

于 2013-08-08T20:07:44.407 回答
9

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

于 2013-08-08T20:59:39.657 回答
1

最初引入关键字是为了表示该volatile值可以由硬件更改。当硬件设备具有内存映射寄存器或内存缓冲区时,就会发生这种情况。正确的方法是仅将其用于此目的。

所有现代同步语言结构和同步库都没有使用这个关键字。应用程序级程序员应该做同样的事情。

于 2013-08-08T23:19:33.297 回答