任何人都可以用简单的英语解释什么是std :: memory_order,以及如何在std :: atomic<>中使用它们?
我在这里找到了参考文献和一些例子,但根本不了解。 http://en.cppreference.com/w/cpp/atomic/memory_order
感谢。
答案 0 :(得分:34)
std::memory_order
值允许您为原子操作提供的内存排序指定细粒度约束。如果您正在修改和访问来自多个线程的原子变量,那么将std::memory_order
值传递给您的操作可以让您放松编译器和处理器上关于操作的顺序的约束这些原子变量对其他线程可见,以及这些操作对应用程序中的非原子数据产生的同步影响。
std::memory_order_seq_cst
的默认排序是最受约束的,它提供了您可能期望的“直观”属性:如果线程A存储了一些数据,然后使用std::memory_order_seq_cst
设置原子标志,那么如果线程B看到标志已设置然后它可以看到线程A写入的数据。其他内存排序值不一定提供此保证,因此必须非常小心地使用。
基本前提是:不要使用std::memory_order_seq_cst
(默认值)以外的任何内容,除非(a)你真的真的知道你在做什么,并且证明< / strong>放松使用在所有情况下都是安全的,并且(b)您的探查器证明您打算使用轻松排序的数据结构和操作是瓶颈。
我的书C++ Concurrency in Action将整整一章(45页)用于C ++内存模型,原子操作和std::memory_order
约束的细节,以及使用原子的另一章(44页)无锁数据结构中的同步操作,以及放宽排序约束的后果。
Dekker's algorithm和Peterson's algorithm上有关互斥的博客文章显示了一些问题。
答案 1 :(得分:22)
任何人都可以用简单的英语解释什么是std :: memory_order,
我发现的各种记忆顺序中最好的“普通英语”解释是Bartoz Milewski关于轻松原子的文章:http://bartoszmilewski.com/2008/12/01/c-atomics-and-memory-ordering/
后续帖子:http://bartoszmilewski.com/2008/12/23/the-inscrutable-c-memory-model/
但请注意,虽然这些文章是一个很好的介绍,但它们早于C ++ 11标准,并且不会告诉您安全使用它们所需要知道的一切。
以及如何将它们与std :: atomic&lt;&gt;?
一起使用
我在这里给你的最好建议是:不要。轻松的原子(可能)是C ++ 11中最棘手和最危险的东西。使用默认的内存排序(顺序一致性)坚持std::atomic<T>
,直到你真的确定你有一个可以通过使用宽松的内存顺序解决的性能问题。
在上面的第二篇文章中,Bartoz Milewski得出以下结论:
在我试图推理时,我不知道自己陷入了什么 关于C ++弱原子。他们背后的理论是如此复杂,以至于它 边界无法使用。花了三个人(安东尼,汉斯和我)和 修改标准以完成相对证明 简单的算法。想象一下,为无锁队列做同样的事情 关于弱原子!
答案 2 :(得分:15)
没有。 “普通英语”解释需要32页,可以找到here。
如果您不想阅读它,您可以忘记内存排序,因为您链接的页面表示默认是顺序一致的排序,这是“始终做得很好” - 设置。
要使用真正的任何其他设置,必须阅读并理解上述文章及其中的示例。
答案 3 :(得分:5)
简而言之,您的编译器和CPU可能会按照与编写指令不同的顺序执行指令。对于单线程,这不是问题,因为它看起来是正确的。对于多个处理器上的多个线程,这成为一个问题。 C ++中的内存排序限制了编译器/ CPU可以执行的操作并修复了这些问题。
例如,如果你查看我在double-check locking上的文章,你可以看到如何使用该模式排序混乱 - 它提到显示原子内存排序可以用来修复它。
关于重新排序本身,您也可以考虑CPU Reordering - 再次,编译器也可能正在进行重新排序。
请注意,有关此主题的任何文件(包括我的)都会提到理论情景。最常见的CPU,如x86,具有非常强大的排序保证,因此根本不需要大量的显式排序。因此,即使您没有使用正确的C ++ 11原子,您的代码仍可能正常工作。
正如zvrba所说,这个话题实际上非常详细。 memory barriers上的linux内核文档也包含大量详细信息。
答案 4 :(得分:4)
GCC wiki中有一些简单的英语。 ;)