c++ 几种内存约束

来源:互联网 发布:mac视频格式是什么 编辑:程序博客网 时间:2024/06/18 18:50

[参考] c++并发内存模型学习

[参考]c++内存模型和原子操作

memory_order_relaxed

最松散,或者说,不执行顺序一致性。该内存操作保证是原子操作,但可以在编译时优化或在运行时被cpu执行任意优化。而且在多核心平台上,relax操作产生的结果可能不会被立即同步到其他核心(没有synchronizes with属性),其他核心不会立即看见这个操作。relax的原子操作与上下文代码没有happens before的关系,也就是没有release语意。

memory_order_acquire和memory_order_release

这对操作具有acquire和release语义,被操作的内存变量在实施操作的核心之间有synchronizes with属性,可以保证源代码及编译后机器码顺序一致,但这种保证仍然不够严格,看这个例子:

 -Thread 1-  y.store (20, memory_order_release);

 -Thread 2-  x.store (10, memory_order_release);

 -Thread 3-  assert (y.load (memory_order_acquire) == 20 && x.load (memory_order_acquire) == 0)

 -Thread 4-  assert (y.load (memory_order_acquire) == 0 && x.load (memory_order_acquire) == 10)

运行时,两个assert都可能同时不触发,在t3角度看来xy的改变顺序与t4角度允许不一致,xy顺序无关,无论在源代码的角度,还是机器码的角度。如果没有t3和t4的观察,xy的执行顺序既是x-y,也是y-x,是不是跟那个什么猫的实验很像。如果要所有核心看来顺序一致,就要用memory_order_seq_cst。

memory_order_consume

与acquire类似,但不会涉及到代码上下文内与原子操作不相关的内存变量,看这个例子:

-Thread 1-  

n = 1  

m = 1

p.store(&n, memory_order_release)

-Thread 2-  

t = p.load(memory_order_acquire);  

assert( *t == 1 && m == 1 );

-Thread 3-  

t = p.load(memory_order_consume);  

assert( *t == 1 && m == 1 );

t3会fail,因为p与m无关,(p只与n有关),所以t3角度只得到n,p的release结果,m没有被同步,相反,t2会同步n、m、及p。

memory_order_acq_rel:acquire + release

memory_order_seq_cst

最严格的顺序一致性,所有标记seq_cst的操作,顺序都不能被打乱(不能被编译器优化,不能被cpu乱序),无论从代码角度(源代码)还是cpu指令流(并发执行)的角度。在任意一个核心看来,所有标记为seq_cst的操作的顺序都一致

0 0
原创粉丝点击