做网编去网站还是工作室好,seo是什么服,搜索引擎优化的重要性,大气的企业网站设计原子操作的内存顺序有六个内存顺序选项可应用于对原子类型的操作#xff1a;1. memory_order_relaxed2. memory_order_consume3. memory_order_acquire4. memory_order_release5. memory_order_acq_rel6. memory_order_seq_cst。除非你为特定的操作指定一个顺序选项#xff0… 原子操作的内存顺序有六个内存顺序选项可应用于对原子类型的操作1. memory_order_relaxed2. memory_order_consume3. memory_order_acquire4. memory_order_release5. memory_order_acq_rel6. memory_order_seq_cst。除非你为特定的操作指定一个顺序选项否则内存顺序选项对于所有原子类型默认都是memory_order_seq_cst。6个内存顺序可以分为3类1. 自由顺序(memory_order_relaxed)2.获取-释放顺序(memory_order_consume, memory_order_acquire, memory_order_release和memory_order_acq_rel)3.排序一致顺序(memory_order_seq_cst)1、std::memory_order_relaxed “自由”内存顺序在原子类型上的操作以自由序列执行没有任何同步关系仅对此操作要求原子性。例如在某一线程中先写入A再写入B。但是在多核处理器中观测到的顺序可能是先写入B再写入A。自由内存顺序对于不同变量可以自由重排序。这是因为不同的CPU缓存和内部缓冲区在同样的存储空间中可以存储不同的值。对于非一致排序操作线程没有必要去保证一致性。#include #include #include std::atomic x,y;std::atomic z; void write_x_then_y(){ x.store(true,std::memory_order_relaxed); y.store(true,std::memory_order_relaxed); }void read_y_then_x(){ while(!y.load(std::memory_order_relaxed)); if(x.load(std::memory_order_relaxed)) z;}int main(){ xfalse; yfalse; z0; std::thread a(write_x_then_y); std::thread b(read_y_then_x); a.join(); b.join(); assert(z.load()!0); }上述代码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用于获取数据放在读操作的最开始 。#include #include #include std::atomic x,y;std::atomic z; void write_x_then_y(){ x.store(true,std::memory_order_relaxed); y.store(true,std::memory_order_release); }void read_y_then_x(){ while(!y.load(std::memory_order_acquire)); // 自旋等待y被设置为true if(x.load(std::memory_order_relaxed)) z;}int main(){ xfalse; yfalse; z0; std::thread a(write_x_then_y); std::thread b(read_y_then_x); a.join(); b.join(); assert(z.load()!0);}上述代码是使用“释放-获取模型对“自由”模型的改进。z.load() ! 0 返回的一定是true。首先a线程中y使用memory_order_release释放内存顺序在多核处理器观测到的顺序x的赋值肯定会位于y之前。b线程中y的获取操作是同步操作x的访问顺序必定在y之后观测到的x的访问值一定为true。“获取”与“释放”一般会成对出现用来同步线程。4、std::memory_order_acq_rel 获取释放内存顺序memory_order_acq_rel带此内存顺序的读-改-写操作既是获得加载又是释放操作。没有操作能够从此操作之后被重排到此操作之前也没有操作能够从此操作之前被重排到此操作之后。std::atomic sync(0);void thread_1(){ // ... sync.store(1,std::memory_order_release);} void thread_2(){ int expected1; while(!sync.compare_exchange_strong(expected,2, std::memory_order_acq_rel)) expected1;}void thread_3(){ while(sync.load(std::memory_order_acquire)2); // ...}上述代码使用memory_order_acq_rel来实现3个线程的同步。thread1执行写入功能thread2执行读取功能。3个线程的执行顺序是确定的。compare_exchange_strong当*this值与expected相同时会将2赋值*this返回true不同时将*this赋值expected返回flase。5、std::memory_order_consume 依赖于数据的内存顺序memory_order_consume只会对其标识的对象保证该对象存储先行于那些需要加载该对象的操作。struct X{int i;std::string s;}; std::atomic p;std::atomic a; void create_x(){ X* xnew X; x-i42; x-shello; a.store(99,std::memory_order_relaxed); p.store(x,std::memory_order_release); } void use_x(){ X* x; while(!(xp.load(std::memory_order_consume))) std::this_thread::sleep(std::chrono::microseconds(1)); assert(x-i42); assert(x-shello); assert(a.load(std::memory_order_relaxed)99); /} int main(){ std::thread t1(create_x); std::thread t2(use_x); t1.join(); t2.join();}x-i 42和x- hello会被确保已被赋值。但是a的值却是不确定的。加载p的操作标记为memory_order_consume这就意味着存储p仅先行那些需要加载p的操作对于a是没有保障的。6、std::memory_order_seq_cst “顺序一致”内存顺序memory_order_seq_cst比std::memory_order_acq_rel更为严格。memory_order_seq_cst不仅是一个获取释放内存顺序它还会对所有拥有此标签的内存操作建立一个单独全序。memory_order_acq_rel的顺序保障是要基于同一个原子变量的。memory_order_acq_rel使用了两个不同的原子变量x1, x2那在x1之前的读写重排到x2之后是完全可能的在x1之后的读写重排到x2之前也是被允许的。然而如果两个原子变量x1,x2是基于memory_order_seq_cst在操作那么即使是x1之前的读写也不能被重排到x2之后x1之后的读写也不能重排到x2之前也就说如果都用memory_order_seq_cst那么程序代码顺序(Program Order)就将会是你在多个线程上都实际观察到的顺序(Observed Order)。顺序一致是最简单、直观的序列但是它也是最昂贵的内存序列它需要对所有线程进行全局同步比其他的顺序造成更多的消耗。因为保证一致顺序需要添加额外的指令。#include #include #include std::atomic x,y;std::atomic z; void write_x(){ x.store(true,std::memory_order_seq_cst); } void write_y(){ y.store(true,std::memory_order_seq_cst); }void read_x_then_y(){ while(!x.load(std::memory_order_seq_cst)); if(y.load(std::memory_order_seq_cst)) z;}void read_y_then_x(){ while(!y.load(std::memory_order_seq_cst)); if(x.load(std::memory_order_seq_cst)) z;}int main(){ xfalse; yfalse; z0; std::thread a(write_x); std::thread b(write_y); std::thread c(read_x_then_y); std::thread d(read_y_then_x); a.join(); b.join(); c.join(); d.join(); assert(z.load()!0); }z.load() ! 0 一定会为true。memory_order_seq_cst的语义会为所有操作都标记为memory_order_seq_cst建立一个单独全序。线程c和d总会有一个执行z x和y的赋值顺序不管谁先谁后在所有线程的眼中顺序都是确定的。来源盐焗咸鱼https://blog.csdn.net/qq_33215865/article/details/88089927