1、std::memory_order_relaxed “自由”内存顺序
在原子类型上的操作以自由序列执行,没有任何同步关系,仅对此操作要求原子性。例如,在某一线程中,先写入A,再写入B。但是在多核处理器中观测到的顺序可能是先写入B,再写入A。自由内存顺序对于不同变量可以自由重排序。
这是因为不同的CPU缓存和内部缓冲区,在同样的存储空间中可以存储不同的值。对于非一致排序操作,线程没有必要去保证一致性。
上述代码,z.load()!=0有可能会返回false。在b线程中,多核处理器观测到的顺序是随机的。b线程中的观测到的变量的并不会与线程a中的变量做同步,没有任何顺序要求。
2、std::memory_order_release “释放”内存顺序
使用memory_order_release的原子操作,当前线程的读写操作都不能重排到此操作之后。例如,某一线程先写入A,再写入B,再以memeory_order_release操作写入C,再写入D。在多核处理器中观测到的顺序AB只能在C之前,不能出现C写入之后,A或B再写入的情况。但是,可能出现D重排到C之前的情况。
memory_order_release用于发布数据,放在写操作的最后。
3、std::memory_order_acquire “获取”内存顺序
使用memory_order_acquire的原子操作,当前线程的读写操作都不能重排到此操作之前。例如,某一线程先读取A,再读取B,再以memeory_order_acquire操作读取C,再读取D。在多核处理器中观测到的顺序D只能在C之前,不能出现先读取D,最后读取C的情况。但是,可能出现A或B重排到C之后的情况。
memory_order_acquire用于获取数据,放在读操作的最开始 。
上述代码是使用“释放-获取"模型对“自由”模型的改进。z.load() != 0 返回的一定是true。首先,a线程中,y使用memory_order_release释放内存顺序,在多核处理器观测到的顺序,x的赋值肯定会位于y之前。b线程中,y的获取操作是同步操作,x的访问顺序必定在y之后,观测到的x的访问值一定为true。
“获取”与“释放”一般会成对出现,用来同步线程。
声明:
本文于网络整理,版权归原作者所有,如来源信息有误或侵犯权益,请联系我们删除或授权事宜。