step4使得c依赖于flag,当step4线程B读取到flag的值为true的时候,由于flag依赖于b,b在之前的写入是可见的,此时b一定为true,所以step6、step7的断言一定会成功。而且这种依赖关系具有传递性,假如b又依赖与另一个变量d,则d在之前的写入同样对step4之后的操作可见。那么a呢?很遗憾在这种内存序下a并不能得到保证,step5的断言可能会失败。
memory_order_acq_rel
这个选项看名字就很像release和acquire的结合体,实际上它的确兼具两者的特性。这个操作用于“读取-修改-写回”这一类既有读取又有修改的操作,例如CAS操作。可以将这个操作在内存序中的作用想象为将release操作和acquire操作捆在一起,因此任何读写操作的重拍都不能跨越这个调用。依然以一个例子来说明,flag为一个 atomic特化的bool 原子量,a、c各为一个int变量,b为一个bool变量,并且刚好按如下顺序执行:
| step | thread A | thread B |
|---|---|---|
| 1 | a = 1 | |
| 2 | flag.store(true, memory_order_release) | |
| 3 | b = true | |
| 4 | c = 2 | |
| 5 | while (!flag.compare_exchange_weak(b, false, memory_order_acq_rel)) {b = true} | |
| 6 | assert(a == 1) | |
| 7 | if (true == flag.load(memory_order_acquire) | |
| 8 | assert(c == 2) |










