有六个内存序列选项可应用于对原子类型的操作:memory_order_relaxed,memory_order_consume,memory_order_acquire,memory_order_release,memory_order_acq_rel以及memory_order_seq_cst。这六个原子序列主要分为三类:排序一致序列(memory_order_seq_cst),获取-释放序列(memory_order_consume,memory_order_acquire,memory_order_release,memory_order_acq_rel)以及自由序列(memory_order_relaxed)。
不同的内存序列模型,允许开发人员利用其提升与更细粒度排序相关的操作。看一下不同操作序列和同步相关的结果。
排序一致序列
默认的就是排序一致序列,它表示程序中的行为从任意角度去看,序列顺序都保持一致。如果原子类型实例上的所有操作都是序列一致的,那么一个多线程的行为,就以某种特殊的排序执行,好像单线程那样。从同步来看,对于同一变量,排序一致的存储操作同步相关与同步一致的载入操作。示例代码如下:
1 |
|
序列一致是最简单、直观的序列,但是他也是最昂贵的内存序列,因为它需要对所有线程进行全局同步。在一个多处理系统上,这就需要处理期间进行大量并且费时的信息交换。为了避免这种同步消耗,需要考虑使用其他模型。
非序列一致内内存模型
在不同线程中看到的相同操作,不一定有着相同的顺序,还有对于不同线程的操作,都会整齐的,一个接着另一个执行的想法都是需要摒弃的。不仅是要摒弃交错执行操作的想法,你还要放弃使用编译器或处理器重排指令的想法。在没有明确的顺序限制下,唯一的要求就是,所有线程都要统一对每一个独立变量的修改顺序。对不同变量的操作可以体现在不同线程的不同序列上,提供的值要与任意附加顺序限制保持一致。当跳出排序一致模型时,最好的就是使用memory_order_relaxed对所有操作进行约束。
自由序列
在原子类型上的操作以自由序列执行,没有任何同步关系。在同一线程中对于同一变量的操作还是服从先发执行的关系,但是不同线程几乎不需要相对的顺序。唯一的要求是在访问同一线程中的单个原子变量不能重排序。当一个给定线程已经看到一个原子变量的特定
值,线程随后的读操作就不会去检索变量较早的那个值。如下示例代码:
1 |
|
获取-释放序列
对于获取释放序列来说,虽然操作依旧没有统一的顺序,但是在这个序列中引入了同步,在这种模型中,原子加载就是获取操作(memory_order_acquire),原子存储就是释放操作(memory_order_release),原子读-改-写操作不是获取就是释放或者两者都有(memory_order_acq_rel).同步在线程释放和获取间,是成对的。
代码示例如下:
1 |
|