C++11 并发-多线程感知内存模型

内存模型基本结构:对象和内存位置

内存顺序

内存模型关系

sequenced-before

表达式的评估顺序,它只在单个线程中被考虑。如语句A && B中会先执行 A,判断为true后再执行 B,更为详细的定义以及规则可参考Order of evaluation

代码的顺序也可以理解为sequenced-before关系,最终执行时满足标准库的 as-if 准则即可

synchronizes-with

指不同线程在原子类型上的操作,如对同一个原子变量,T2 中的load synchronizes-with T1 中的store

carries dependency

即依赖关系

dependency-ordered before

即release-consume ordering

inter-happens-before

线程间的happens-before关系,它依赖于synchronizes-with关系或dependency-ordered before关系

happens-before

同一线程即sequenced-before关系,不同线程即inter-happens-before关系

原子操作的内存顺序

sequentially consistent ordering

顺序一致顺序,std:: memory_order_seq_cst,它是所有原子操作内存顺序参数的默认值:

  • 所有原子类型实例上的操作是顺序一致的
  • 所有线程都必须看到相同的操作顺序

顺序一致是最直观的排序,但也是最昂贵的内存顺序,因为它要求所有线程之间的全局同步。在多处理器系统中,这可能需要处理器之间相当密集和耗时的通信

另外可以参考有关sequential和order的理解,简单来讲sequential是一个接一个的意思,顺序执行,没有重叠;order指经过一定的调整,让某样东西按照一定的规则变得有序;sequential order 就是指让操作一个接一个的排列,并且没有重叠

release-acquire ordering

释放-获取顺序,指定std::memory_order_acquire内存顺序的原子载入(load)是获取(aquire)操作,指定std::memory_order_release内存顺序的原子存储(store)是释放(relase)操作,指定std::memory_order_acq_rel内存顺序的原子的读-修改-写(如fetch_add()、exchange())是获取操作 、释放操作或两者兼备

当两个线程 T1、T2 满足释放-获取顺序时,T2 中原子载入(load)操作完成后,T2 中后续操作将会看到 T1 中原子存储(store)操作之前的所有的写内存操作(带来的结果)

release-consume ordering

释放-消费顺序,指定std::memory_order_consume内存顺序的原子载入(load)是消费(consume)操作

当两个线程 T1、T2 满足释放-获取顺序时,T2 中原子载入(load)操作完成后,T2 中对这个load操作有依赖的后续操作才将会看到 T1 中原子存储(store)操作之前的所有的写内存操作(带来的结果)

relaxed ordering

松散顺序,std::memory_order_relaxed,以松散顺序执行的原子类型上的操作不参与synchronizes-with关系:

  • 单线程中的同一个变量的操作仍然服从happens-before(sequence before)关系,但相对于其他线程的顺序几乎没有任何要求
  • 不同变量的松散操作可以被自由地重排

参考

《C++ Concurrency IN ACTION》
Memory model
std::memory_order
The as-if rule
Is the explanation of relaxed ordering erroneous in cppreference?
Does sequenced-before relation in C++11 prevent compiler/CPU reordering?
How to determine what is 'sequenced before' others?

原文地址:https://www.cnblogs.com/wangzhiyi/p/13336191.html