C 中的 volatile int 与 std::atomic一样好吗? C++0x 的?
我的程序中需要有原子变量。以前我使用的是 std::atomic
,但我现在工作的平台没有支持 C++0x 的 g++ 编译器。我使用了 volatile int ,它似乎有效,因为我在测试它的多核系统中还没有遇到竞争条件。
我的问题是 volatile int
是否像 std::atomic
一样atomic?另外,它是否会产生内存障碍(我也需要)?
I need to have atomic variables in my program. Previously I was using std::atomic<int>
, but the platform in which I'm working now does not have a g++ compiler that supports C++0x. I used volatile int
and it seems to be working, as I haven't experienced a race condition yet in the multicore system I'm testing it on.
My question is if volatile int
is atomic like std::atomic<int>
? Also, does it creates memory barriers (which I also require)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不。
易失性
与多线程无关。它不会强制执行内存屏障(尽管有些编译器可能会选择添加该屏障),并且它不保证对非易失性对象的读/写重新排序。添加了 易失性 来支持写入内存映射的硬件 I/O 寄存器,在这种情况下,重要的是您的写入不会被优化,但没有精确的顺序保证。需要非易失性读/写。
您可能还想阅读 这个
No.
volatile
has nothing to do with multithreading. It doesn't enforce a memory barrier (although some compilers might choose to add that anyway), and it makes no guarantees about read/write reordering with respect to non-volatile objects.volatile
was added to support writing to memory-mapped hardware I/O registers, and such cases, where it is important that your write isn't optimized away, but no precise ordering guarantees wrt. non-volatile reads/wrties are required.You might also want to read this
易失性变量并不意味着内存屏障,并且没有
std::atomic
的exchange
或compare_exchange_*
操作。它们确实避免了编译器在机器代码级别将一个负载提升为多个负载(反之亦然,对于存储也类似),但仅此而已。您可能对这些文章感兴趣:
如果您没有
std::atomic
,您可能需要使用 boost::atomic,或者使用您所使用的任何编译器提供的低级屏障和原子操作原语。Volatile variables do NOT imply memory barriers, and do not have the
exchange
orcompare_exchange_*
operations ofstd::atomic
. They do avoid the compiler lifting a load into multiple loads on the machine code level (and vice versa, and similar for stores) but that's it.You may be interested in these articles:
If you do not have
std::atomic
, you may want to use boost::atomic, or use the low-level barrier and atomic-operation primitives offered by whatever compiler you're using.我看到你在一些评论中询问 GCC,就在这里。
GCC 用于原子内存访问的内置函数
I've seen you asking about GCC in some comments, here you go.
GCC's Built-in functions for atomic memory access
易失性基本上告诉编译器它不能对特定内存位置中的内容做出假设。例如,
编译器可能会优化整个
while
,因为它假设test
始终为 true。然而,如果test
在某个时刻将从其他地方(例如某些硬件或另一个线程)更新,我们不希望编译器假设它知道test
中的内容>。我们可以告诉编译器使用易失性
。正如其他答案所说,它不能保证事物访问内存位置的顺序。Ps
我无耻地从某个地方偷了这个例子,但不记得在哪里看到它了。
volatile
basically tells the compiler it can't make assumptions about what is in a particular memory location. For instancethe compiler might optimize away the whole
while
because it assumestest
is always true. If howevertest
is at some point going to be updated from elsewhere (some hardware or another thread for instance) the we do not want the compiler to assume it knows what is intest
. We can tell the compiler that usingvolatile
.As the other answers say, it gives no guarantees about what order things access the memory location in.
P.s. I shamelessly stole that example from somewhere but can't remember where I saw it.
在 C++0x 之前,该语言不支持线程,因此它不会阻止多重访问。声明它是不稳定的会对一些人有所帮助,但它不会阻止竞争。
有关更多详细信息,请参阅 http://en.wikipedia.org/wiki/Volatile_variable。
要真正使操作原子化,您需要使用线程库(win32 线程、pthreads 等)提供的任何锁定机制。
Before C++0x, the language wasn't thread aware, so it did not prevent multiple access. Declaring it volatile will help some, but it won't prevent races.
See http://en.wikipedia.org/wiki/Volatile_variable for more details.
To truly make operations atomic, you'll need to employ whatever locking mechanism your threading library (win32 threads, pthreads, etc) provides.
Herb Sutter 在此处对差异进行了很好的总结。总结(剪切和粘贴):
There's a good summary of the diffs here, from Herb Sutter. In summary (cut and paste):