目录
- 1,六大内存序
- 2,原子操作
- 2.1,原子操作的核心操作,基础操作:store 和 load
- 3,利用内存模型和原子操作的生产者消费者模型设计
1,六大内存序
| 内存顺序 | 类型 | 核心特点 |
|---|---|---|
| memory_order_relaxed | 宽松(无同步) | 只保证原子性,不保证顺序。不引入同步屏障,允许编译器和 CPU 任意重排 |
| memory_order_consume | 消费(已过时) | 依赖当前原子变量的后续操作不被重排到它之前。(不推荐使用,编译器通常降级为 acquire) |
| memory_order_acquire | 获取(读屏障) | 该原子读操作之后的所有读写操作都不能重排到该操作之前。 |
| memory_order_release | 释放(写屏障) | 该原子写操作之前的所有读写操作都不能重排到该操作之后 |
| memory_order_acq_rel | 获取-释放(读写屏障) | 同时具备 acquire 和 release 效果,用于 Read-Modify-Write 操作(如 exchange)。 |
| memory_order_seq_cst | 顺序一致性(最强) | 全局所有线程看到统一的修改顺序,最强最直观,但性能开销最大。 |
,
,
1,memory_order_release 释放----写屏障 可以理解为,原子操作的时候进行写操作,在写完释放给别的线程读之前,
必须把此线程在自身缓冲区写的数据全部同步到 公共的缓存中?
“线程在执行 Release 写操作时,必须确保本线程在 Release 之前发生的所有写操作,
都已经对其它核心可见(即排空到共享缓存),然后才允许执行 Release 这个写操作本身。”
,
2,memory_order_acquire 获取----读屏障 可以理解为,必须先将公共区的数据都读完之后,在进行其他的操作,比如写操作。
,
,
2,原子操作
原子操作(Atomic Operation)是指不可被中断的一个或一系列操作。在多线程环境中,原子操作要么全部执行完成,要么完全不执行,不会出现"执行到一半被其他线程干扰"的情况。
2.1,原子操作的核心操作,基础操作:store 和 load
| 操作 | 函数原型 | 允许的内存顺序 |
|---|---|---|
| 写入 | void store(T desired, memory_order order = seq_cst) | relaxed, release, seq_cst |
| 读取 | T load(memory_order order = seq_cst) const | relaxed, acquire, seq_cst |
std::atomic<int>value{0};// store 操作value.store(42);// 默认 seq_cstvalue.store(100,std::memory_order_release);// 显式指定 releasevalue.store(1,std::memory_order_relaxed);// 最弱的顺序// load 操作int x=value.load();// 默认 seq_cstint y=value.load(std::memory_order_acquire);// 显式指定 acquireint z=value.load(std::memory_order_relaxed);// 最弱的顺序store 不能使用 memory_order_acquire 或 memory_order_acq_rel
load 不能使用 memory_order_release 或 memory_order_acq_rel
,
,
| 操作 | 函数原型 | 说明 |
|---|---|---|
| 交换 | T exchange(T desired, memory_order order = seq_cst) | 用新值替换旧值,返回旧值 |
| CAS(弱) | bool compare_exchange_weak(T& expected, T desired, …) | 可能虚假失败,适合循环 |
| CAS(强) | bool compare_exchange_strong(T& expected, T desired, …) | 不会虚假失败 |
| 算术 | T fetch_add(T arg, memory_order order = seq_cst) | 加、减、与、或、异或 |
std::atomic<int>counter{10};// exchange:交换并返回旧值int old=counter.exchange(20);// old = 10, counter = 20// fetch_add:原子加int previous=counter.fetch_add(5);// previous = 20, counter = 25// compare_exchange:CAS(Compare-And-Swap)int expected=25;if(counter.compare_exchange_strong(expected,100)){// 如果 counter 当前是 25,替换为 100,expected 不变std::cout<<"替换成功!counter = 100"<<std::endl;}else{// 替换失败,expected 被更新为 counter 的实际值std::cout<<"替换失败,当前值为:"<<expected<<std::endl;}| 特性 | compare_exchange_weak | compare_exchange_strong |
|---|---|---|
| 虚假失败 | ✅ 可能(即使相等也返回 false) | ❌ 不会(相等一定返回 true) |
| 性能 | 更快(某些平台可用 LL/SC 优化) | 稍慢(需要重试处理) |
| 典型用法 | 循环中(while + weak) | 单次检查 |
| 返回值 | bool(成功/失败) | bool(成功/失败) |
// ✅ weak 的正确用法:在循环中重试std::atomic<int>value{0};int expected=0;while(!value.compare_exchange_weak(expected,100,std::memory_order_acq_rel)){// 失败时 expected 被更新为实际值// 这里可以加一个最大重试次数限制}// ✅ strong 的典型用法:单次检查int expected=0;if(value.compare_exchange_strong(expected,100,std::memory_order_acq_rel)){// 成功处理}3,利用内存模型和原子操作的生产者消费者模型设计
#include<iostream>#include<thread>#include<atomic>std::atomic<int>count{0};// 共享整形变量,初始为 0(绝对主角!)std::atomic<bool>ready{false};// 同步标志:true=有货待消费,false=已消费// ========== 生产者:count 不断加一 ==========voidproducer(){for(int i=1;i<=10;++i){// ① 直接修改 count(加一操作)// 使用 release,保证这次写入完成之前,之前的所有操作都已完成count.store(i,std::memory_order_release);// ② 通知消费者:count 已经更新,快来打印!// 必须用 release,保证 count 的写入在通知之前可见ready.store(true,std::memory_order_release);// ③ 等待消费者打印完成(等待 ready 被改回 false)while(ready.load(std::memory_order_acquire)){// 自旋等待,CPU 会忙等}}}// ========== 消费者:打印 count 的当前值 ==========voidconsumer(){for(int i=1;i<=10;++i){// ① 等待生产者通知(等待 ready 变成 true)while(!ready.load(std::memory_order_acquire)){// 自旋等待}// ② 读取 count 的最新值并打印// 用 acquire 保证读到的 count 一定是生产者 release 写进去的最新值int value=count.load(std::memory_order_acquire);std::cout<<"消费者打印: count = "<<value<<std::endl;// ③ 告诉生产者:我已经打印完了,你可以生产下一个了// 用 release 保证“打印完成”这个动作在改 ready 之前完成ready.store(false,std::memory_order_release);}}intmain(){std::threadt1(producer);std::threadt2(consumer);t1.join();t2.join();return0;}