C++ 11引入了标准化的内存模型,但究竟是什么意思呢?它将如何影响C++编程?
这篇文章(引用Herb Sutter的Gavin Clarke)说,
内存模型意味着C++代码现在有一个标准化的库可以调用,无论是谁编译器以及它运行的平台.有一种标准方法可以控制不同线程与处理器内存的对话方式.
"当你谈论在标准中的不同内核之间分割[代码]时,我们正在谈论内存模型.我们将优化它,而不会破坏人们将在代码中做出的以下假设," Sutter说.
好吧,我可以在网上记住这个和类似的段落(因为我从出生以来就拥有自己的记忆模型:P),甚至可以发布作为其他人提出的问题的答案,但说实话,我并不完全明白这个.
C++程序员以前用于开发多线程应用程序,那么如果它是POSIX线程,Windows线程或C++ 11线程,它又如何重要呢?有什么好处?我想了解低级细节.
我也觉得C++ 11内存模型与C++ 11多线程支持有某种关系,因为我经常将这两者结合在一起.如果是,究竟是怎么回事?他们为什么要相关?
由于我不知道多线程的内部工作原理以及内存模型的含义,请帮助我理解这些概念.:-)
有人能用一种凡人理解的语言解释它吗?
任何人都可以用简单的英语解释什么是std :: memory_order,以及如何将它们与std :: atomic <>一起使用?
我在这里找到了参考文献和一些例子,但根本不了解. http://en.cppreference.com/w/cpp/atomic/memory_order
谢谢.
C++ 11标准定义了一个内存模型(1.7,1.10),它包含内存排序,大致是"顺序一致","获取","消费","释放"和"放松".同样粗略地说,程序只有在没有竞争的情况下才是正确的,如果所有动作都可以按照某个动作的顺序放在另一个动作之前,则会发生这种情况.动作 X发生的方式 - 在动作Y 之前是X在Y之前(在一个线程内)被排序,或者X在线程间 - 在Y之前发生.其中,后者的条件是在何时
当X是在某个原子变量上具有"释放"排序的原子存储时发生同步,并且Y是在同一变量上具有"获取"排序的原子加载.作为依赖项,订购前发生了类似的情况,其中Ÿ是负载"消费"排序(和合适的内存访问).的概念下同步,与延伸的之前发生关系传递性跨越的行动被测序,之前彼此线程内,但被相关性排序,之前只有通过严格的子集传递性扩展测序,之前叫依赖于大规模规则的依赖性,特别是可以被中断std::kill_dependency.
那么,"依赖性排序"概念的目的是什么?与简单的排序 - 先前/同步 -排序相比,它提供了什么优势?由于它的规则更严格,我认为可以更有效地实施.
你能举一个程序的例子,从发布/获取到发布/消费的转换是正确的,并提供一个非平凡的优势吗?何时能std::kill_dependency提供改进?高级别参数会很好,但硬件特定差异的奖励点.
我一直在阅读有关新C++ 11内存模型的内容,并且我已经开始使用该std::kill_dependency功能(§29.3/ 14-15).我很难理解为什么我会想要使用它.
我在N2664提案中找到了一个例子,但它并没有多大帮助.
它首先显示代码而不是std::kill_dependency.这里,第一行将依赖性携带到第二行中,第二行将依赖性携带到索引操作中,然后将依赖性携带到do_something_with函数中.
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(a[r2]);
Run Code Online (Sandbox Code Playgroud)
还有一个例子std::kill_dependency用于打破第二行和索引之间的依赖关系.
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(a[std::kill_dependency(r2)]);
Run Code Online (Sandbox Code Playgroud)
据我所知,这意味着索引和调用do_something_with不是在第二行之前排序的依赖项.根据N2664:
这允许编译器将调用重新排序
do_something_with,例如,通过执行预测值的推测优化a[r2].
为了使得需要调用do_something_with该值a[r2].假设编译器"知道"数组填充了零,它可以根据需要优化该调用do_something_with(0);并相对于其他两个指令重新排序此调用.它可以产生以下任何一种:
// 1
r1 = x.load(memory_order_consume);
r2 = r1->index;
do_something_with(0);
// 2
r1 = x.load(memory_order_consume);
do_something_with(0);
r2 = r1->index;
// 3
do_something_with(0);
r1 = x.load(memory_order_consume);
r2 = r1->index;
Run Code Online (Sandbox Code Playgroud)
我的理解是否正确?
如果do_something_with通过其他方式与另一个线程同步,这对于x.load调用的顺序和另一个线程意味着什么?
假设我的描述是正确的,那还有一件事让我感到困惑:当我编写代码时,是什么原因导致我选择杀死依赖?
java内存模型强制要求写一个int是原子的:也就是说,如果你在一个线程中写一个值(由4个字节组成)并在另一个线程中读取它,你将获得所有字节或没有,但永远不会有2个新字节和2个旧字节或类似的.
这不保证long.在这里,写入之前0x1122334455667788保存的变量0可能导致另一个线程读取0x112233440000000或0x0000000055667788.
现在,规范并未强制对象引用为int或long.出于类型安全的原因,我怀疑它们是保证以原子方式编写的,但在64位VM上,这些引用可能是非常好的64位值(仅仅是内存地址).
现在我的问题是:
此致,斯蒂芬
我读了一章,我不喜欢它.我还不清楚每个内存顺序之间的差异.这是我目前的推测,我在阅读更简单的http://en.cppreference.com/w/cpp/atomic/memory_order后理解这一点.
以下是错误的,所以不要试图从中学习
a在另一个线程上放宽了存储.我b用seq_cst 存储.第三个线程读取a 放松将看到变化以及b任何其他原子变量? ).如果我错了,我想我理解但是纠正我.我找不到任何用易于阅读的英语解释它的东西.
新的c ++标准引入了内存模型的概念.关于它的问题已经有了问题,它是什么意思,它如何改变我们用c ++编写代码的方式等等.
我有兴趣了解C++内存模型与旧的,众所周知的Java内存模型(1.5)的关系.它是一样的吗?它是相似的吗?他们有什么重大差异吗?如果是这样,为什么?
java内存模型已经存在很长时间了很多人都知道它非常不错,所以我想通过比较它来学习C++内存模型可能会有所帮助.
C++ 03中的并发内存模型是什么?
(而且,C++ 11是否会更改内存模型以更好地支持并发性?)
在查看Clang和g ++ C++ 11实现状态时,我注意到一些奇怪的东西:
它们支持C++ 11原子,但它们不支持C++ 11内存模型.
我的印象是你必须有C++ 11内存模型才能使用原子.那么对原子和内存模型的支持究竟有什么区别呢?
缺乏内存模型支持意味着合法的C++ 11程序使用std::atomic<T>不一致的seq吗?
参考:
http://clang.llvm.org/cxx_status.html
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html
memory-model ×10
c++ ×9
c++11 ×7
atomic ×4
java ×2
c++03 ×1
concurrency ×1
reference ×1
stdatomic ×1