C++内存序
C++11并发操作的内存序
原子操作的关系
Synchronized-with
If thread A stores a value and thread B reads that value, there’s a synchronizes-with relationship between the store in thread A and the load in thread B.
Happens-before
- 单线程:如果一个操作 A 排列在另一个操作 B 之前,那么这个操作 A happens-before B,一般单线程叫A sequenced-before B。
- 多线程:对于多线程而言, 如果一个线程中的操作A先于另一个线程中的操作B, 那么 A happens-before B(一般多线程间操作叫A inter-thread happens-before B)。
六种内存顺序
typedef enum memory_order { |
Relaxed ordering
- 标记为
memory_order_relaxed
的原子操作不是同步操作,不强制要求并发内存的访问顺序,只保证原子性和修改顺序一致性
Release-Consume ordering
对于标记为
memory_order_consume
原子变量 x 的读操作 R,当前线程中依赖于 x 的读写不允许重排到 R 之前,其他线程中对依赖于 x 的变量写操作对当前线程可见consume语义是一种弱的acquire,它只对关联变量进行约束,这个实际编程中基本不用,且在某些情况下会自动进化成acquire语义(比如当用consume语义修饰的load操作在if条件表达式中时)。另外,C++17标准明确说明这个语义还未完善,建议直接使用acquire。
Release-Acquire ordering
- 在release之前的所有store操作绝不会重排到(不管是编译器对代码的重排还是CPU指令重排)此release对应的操作之后,也就是说如果release对应的store操作完成了,则C++标准能够保证此release之前的所有store操作肯定已经先完成了,或者说可被感知了;
- 在acquire之后的所有load操作或者store操作绝对不会重排到此acquire对应的操作之前,也就是说只有当执行完此acquire对应的load操作之后,才会执行后续的读操作或者写操作。
|
Sequentially-consistent ordering
- memory_order_seq_cst 是所有原子操作的默认选项,可以省略不写
- 对于标记为 memory_order_seq_cst 的操作,大概行为就是对每一个变量都进行上面所说的Release-Acquire操作,读操作相当于 memory_order_acquire,写操作相当于 memory_order_release,读改写操作相当于 memory_order_acq_rel,此外还附加一个单独的 total ordering,即所有线程对同一操作看到的顺序也是相同的。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LZY的Code生活!