C ++ 11内存排序 - 差异?

时间:2014-04-10 21:44:47

标签: c++ multithreading c++11 concurrency atomic

我目前正在阅读“并发行动”和第111页,它提供了与std::atomic_flag相关的示例代码,以解释内存排序的工作原理:

f.clear(std::memory_order_release);
bool x = f.test_and_set();

但它只是说:

  

这里,对clear()的调用明确请求标志为   通过释放语义清除,同时调用test_and_set()   使用默认的内存顺序来设置标志和检索   旧的价值。

他们实际上并没有解释出差异是什么。有人可以提供这些内存排序如何工作的一般概述吗?所以不仅仅是我上面提到的那个,但我相信还有一些:

memory_order_relaxed
memory_order_release
memory_order_seq_cst
memory_order_consume
memory_order_acquire
memory_order_acq_rel

1 个答案:

答案 0 :(得分:1)

非正式表征(用一袋盐服用):

  • SEQ_CST:只要没有数据竞争,代码的行为就好像它是一个简单的线程交错,没有重新排序的可观察性。
  • RELEASE / ACQUIRE:发布“发布”一次写入,同一内存位置的读取与该写入同步。例如,互斥锁可以执行 ACQUIRE ,互斥锁可以解锁 RELEASE 。另一个例子:

示例(在括号上标记其内存顺序的原子操作):

t1:                                   t2:
   data = foo                            while not data_valid; (ACQUIRE)
   data_valid = true; (RELEASE)          bar = data;
  • ACQ_REL:同时执行原子RMW(读取 - 修改 - 写入)操作的获取和释放。请注意,您可以指定使用 ACQ_REL 表示成功的RMW,如果RMW操作失败则指定另一个内存顺序。
  • RELEASE / CONSUME:您发布了一个指向结构的指针,并且读取“消耗”该发布,并且可以访问指向的数据。一些Alpha处理器具有拆分缓存,这意味着您可能正在从缓存库中读取指针,并且指向的数据可能不会仍然存在于该缓存的其他存储库中。在Linux上实现的RCU中,rcu_derefence()负责在读取指针和取消引用之间在Alpha上插入读屏障。请注意,有一些关于完全改变消耗内存顺序规范的讨论(在名为"arch: atomic rework"的邮件列表线程上),因为它似乎对编译器编写者来说是不切实际的。特别是,当前标准允许您发布p*(q + (p-p))依赖于此。有些人认为根本没有任何意义。
  • 放松:对所有人免费。