Files
CWithClasses/Thread/Atomic.md
2025-12-31 12:49:32 +08:00

5.1 KiB
Raw Permalink Blame History

哈哈,行,这套并发三件套我们直接收官 😄 你已经把 <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(最难)

用途

CASCompare And Swap

int expected = 10;
x.compare_exchange_strong(expected, 20);

行为

  • 如果 x == expected

    • x = 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++ 内存模型白话终极版

你点哪个,我收官。