5.1 KiB
5.1 KiB
哈哈,行,这套并发三件套我们直接收官 😄
你已经把 <thread>、<mutex> 啃完了,现在这个 <atomic> 是精华也是雷区。
我给你一份能当“原子操作说明书”的完整速查版。
一、<atomic> 是干嘛的?一句话版
<atomic>用来做“无锁但安全”的共享小数据。
关键词只有三个:
- 小
- 简单
- 高频
典型:计数器、标志位、状态机。
二、std::atomic<T> 基础
1️⃣ 定义原子变量
#include <atomic>
std::atomic<int> x{0};
支持的常见类型
int / bool / long- 指针
- 枚举
- trivially copyable 类型(有限)
2️⃣ 读 / 写(load / store)
x.store(10);
int v = x.load();
默认内存序
memory_order_seq_cst(最安全、最慢)
返回值
store:❌ 无load:✔ 返回值
3️⃣ 原子赋值(像普通变量一样)
x = 5;
int y = x;
✔ 语法糖
✔ 等价于 store / load
三、原子读改写(重点)
4️⃣ fetch_add / fetch_sub
int old = x.fetch_add(1);
语义
- 返回 修改前的值
- 然后再加
x++; // 等价 fetch_add(1)
--x; // fetch_sub(1)
返回值
✔ 修改前的值
5️⃣ exchange() —— 原子替换
int old = x.exchange(42);
作用
-
原子地:
- old ← x
- x ← 42
返回值
✔ 旧值
6️⃣ compare_exchange_weak / strong(最难)
用途
CAS(Compare And Swap)
int expected = 10;
x.compare_exchange_strong(expected, 20);
行为
-
如果
x == expectedx = 20- 返回
true
-
否则
expected = x- 返回
false
返回值
✔ bool
weak vs strong
| 版本 | 特点 |
|---|---|
weak |
可能失败(用于循环) |
strong |
不会伪失败 |
四、指针原子(很实用)
7️⃣ std::atomic<T*>
std::atomic<Node*> p;
常用操作
Node* old = p.load();
p.store(new_node);
p.compare_exchange_strong(old, new_node);
👉 无锁链表、对象切换神器
五、内存序(进阶但你必须知道)
默认你可以全用
seq_cst,不会错。
常见枚举
std::memory_order_relaxed
std::memory_order_acquire
std::memory_order_release
std::memory_order_acq_rel
std::memory_order_seq_cst
什么时候用?
| 场景 | 内存序 |
|---|---|
| 简单计数 | relaxed |
| 生产者 / 消费者 | acquire / release |
| 不想翻车 | seq_cst |
示例(生产者-消费者)
data = 42;
flag.store(true, memory_order_release);
while (!flag.load(memory_order_acquire));
use(data);
六、原子标志(最轻量)
8️⃣ std::atomic_flag
std::atomic_flag f = ATOMIC_FLAG_INIT;
操作
f.test_and_set(); // 返回旧值
f.clear();
✔ 自旋锁 ✔ 最底层
七、等待 / 通知(C++20)
9️⃣ wait / notify_one / notify_all
x.wait(0);
x.store(1);
x.notify_one();
作用
- 原子级别的条件变量
- 无 mutex
返回值
❌ 无
八、完整 API 总表(收藏)
| API | 作用 | 返回值 |
|---|---|---|
atomic<T> |
原子变量 | — |
load() |
原子读 | T |
store() |
原子写 | void |
exchange() |
替换 | T |
fetch_add() |
加 | T |
fetch_sub() |
减 | T |
compare_exchange_weak() |
CAS | bool |
compare_exchange_strong() |
CAS | bool |
atomic_flag |
最小原子 | — |
test_and_set() |
设置并返回旧值 | bool |
clear() |
清空 | void |
wait() |
等待 | void |
notify_one() |
唤醒一个 | void |
notify_all() |
唤醒全部 | void |
九、什么时候用 atomic?一句判断法
如果共享数据:
- 类型简单
- 操作简单
- 不涉及多个变量一致性
👉 atomic
否则:
👉 mutex
🔥 十、新手 atomic 四大雷区(务必避开)
1️⃣ 以为 atomic 能解决一切(不能) 2️⃣ 多个 atomic 组合 ≠ 原子整体 3️⃣ 乱用 relaxed 4️⃣ atomic + 普通变量混用无同步
十一、你现在的并发地图已经完整了
thread → 干活
mutex → 防抢
atomic → 快而小
future → 拿结果
你现在完全可以:
- 看懂并发代码
- 写不翻车的并发
- 判断“该不该多线程”
如果你愿意,最后一关我可以带你做:
- 🔥 一个 无锁队列(atomic + CAS)
- 🔥 或把你之前那个拷贝工具 升级成 atomic 进度条
- 🔥 或讲 C++ 内存模型白话终极版
你点哪个,我收官。