C++11内存排序-差异



我目前正在阅读《操作中的并发》,在第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

非正式表征(带着一袋盐):

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

示例(括号中标记了原子操作的内存顺序):

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

相关内容

  • 没有找到相关文章

最新更新