我需要在我的程序中使用原子变量。以前我使用std::atomic<int>
,但我现在正在使用的平台没有支持C ++ 0x的g ++编译器。我使用了volatile int
它似乎正在工作,因为我还没有在多核系统中遇到竞争条件我正在测试它。
我的问题是volatile int
是否像<{1}}一样原子?此外,它是否会产生内存障碍(我也需要)?
答案 0 :(得分:28)
没有。 volatile
与多线程无关。它不会强制执行内存屏障(尽管某些编译器可能会选择添加无论如何),并且它不保证对非易失性对象进行读/写重新排序。
volatile
以支持写入内存映射硬件I / O寄存器,在这种情况下,重要的是你的写入没有被优化掉,但没有精确的顺序保证wrt。需要非易失性读/写。
您可能还想阅读this
答案 1 :(得分:6)
易变变量并不意味着内存障碍,并且没有exchange
的{{1}}或compare_exchange_*
操作。它们确实避免了编译器在机器代码级别上将负载提升到多个负载(反之亦然,并且类似于商店),但就是这样。
您可能对这些文章感兴趣:
如果您没有std::atomic
,则可能需要使用boost::atomic,或者使用您正在使用的任何编译器提供的低级屏障和原子操作原语。
答案 2 :(得分:4)
我见过你在一些评论中询问GCC,你走了。
答案 3 :(得分:1)
在C ++ 0x之前,该语言不是线程感知的,因此它不会阻止多次访问。宣布它不稳定将有所帮助,但它不会阻止比赛。
有关详细信息,请参阅http://en.wikipedia.org/wiki/Volatile_variable。
要真正使操作成为原子,您需要使用线程库(win32线程,pthreads等)提供的任何锁定机制。
答案 4 :(得分:1)
来自Herb Sutter的差异here有一个很好的总结。总结(剪切和粘贴):
安全地编写无锁代码 线程之间没有通信 使用锁,更喜欢使用有序 原子变量:Java / .NET volatile, C ++ 0x原子,与C兼容 atomic_T。
安全地与特殊沟通 硬件或其他内存 不寻常的语义,使用不可优化 变量:ISO C / C ++ volatile。 记住读写 这些变量不一定 然而,原子。
答案 5 :(得分:1)
volatile
基本上告诉编译器它不能对特定内存位置的内容做出假设。例如
bool test = true;
while(!test)
{
/* do something (e.g. wait) */
}
编译器可能会优化整个while
,因为它假定test
始终为真。但是,如果test
在某个时刻将从其他地方(例如某些硬件或其他线程)更新,我们不希望编译器假设它知道test
中的内容。我们可以告诉编译器使用volatile
。
正如其他答案所说,它无法保证在什么顺序访问内存位置。
P.S。我无耻地从某个地方偷走了这个例子,但不记得我在哪里看到它。
答案 6 :(得分:0)