std::atomic 解决多线程下变量读-改-写竞态问题,通过硬件/编译器级原子操作保证 load/store、++、CAS 等操作不可分割;支持平凡可复制的小型类型,需显式声明,不替代 mutex 的多步逻辑保护。

std::atomic 能解决什么问题?
当多个线程同时读写同一个变量(比如 int counter = 0;),++counter 不是原子的:它实际包含「读取→加1→写回」三步。两个线程可能同时读到 0,各自加 1 后都写回 1,结果丢失一次递增。这就是竞态条件。std::atomic 把这类操作打包成不可打断的单步指令,让读-改-写变成一个整体,从硬件或编译器层面阻止交错。
哪些操作能用 std::atomic 安全替代?
常见整型、指针类型支持直接替换,但必须显式声明为 std::atomic,不能对普通变量临时套用原子函数。以下操作默认是原子的(无需额外锁):
-
load()和store(value)—— 带内存序的读/写 -
operator++()、operator+=()—— 复合赋值(如counter++) -
compare_exchange_weak(expected, desired)—— CAS(Compare-And-Swap),实现无锁数据结构的核心
注意:std::atomic、std::atomic、std::atomic 是标准保证可锁自由(lock-free)的;而 std::atomic<:string> 不合法 —— 类型必须是平凡可复制(trivially copyable)且大小适中(通常 ≤ 指针宽度)。
不指定内存序会怎样?
默认使用 std::memory_order_seq_cst(顺序一致性),最安全但也最慢 —— 编译器和 CPU 会插入大量屏障防止重排。实际中可根据场景降级:
立即学习“C++免费学习笔记(深入)”;
- 仅需避免自身读写重排?用
std::memory_order_relaxed(如计数器) - 需要“写后读可见”?用
std::memory_order_acquire(读) +std::memory_order_release(写)配对 - CAS 失败时通常用
relaxed,成功路径才考虑更强序
错误示例:
std::atomic这里必须用flag{0}; // 线程 A: flag.store(1, std::memory_order_relaxed); // 这个 store 可能被重排到后面语句之后 data_ready = true; // 线程 B: if (flag.load(std::memory_order_relaxed) == 1) { use(data_ready); // data_ready 可能还是 false! }
release/acquire 配对才能保证 data_ready 的写入对 B 可见。
std::atomic 不能替代 mutex 的地方
它只保单个变量的读写原子性,无法保护多步逻辑。比如「检查值是否为 0,是则设为 1」需要 CAS 循环,而「先删节点再更新头指针再释放内存」这种多对象协作,仍需 std::mutex 或更高级的无锁设计。
另外,std::atomic 对象本身不可拷贝(只有移动或赋值),也不能作为容器元素直接存储(需用 std::vector<:atomic>*> 或包装成 struct);调试时打印其值要用 .load(),直接 std::cout 会编译失败。









