std::atomic是C++无锁编程核心工具,提供原子读写、CAS等操作,支持整型/指针等类型,需用load/store/exchange/compare_exchange等成员函数操作,不支持普通赋值和算术运算符。

在C++中,std::atomic是实现无锁编程的核心工具,它保证对共享变量的读、写、修改操作具有原子性,避免数据竞争,无需互斥锁(如std::mutex)即可安全地在多线程间同步。
基本用法:声明与初始化
使用std::atomic需包含头文件。它是一个模板类,支持整型、指针等可平凡复制(trivially copyable)类型。常用特化包括std::atomic、std::atomic、std::atomic等。
初始化方式有多种:
- 直接构造:
std::atomiccounter{0}; - 使用
.store()赋值:counter.store(42); - 使用初始化列表(C++20起支持聚合初始化):
std::atomicx = {100};
核心操作:load、store、exchange、compare_exchange
原子变量不支持普通赋值和算术运算符重载(如++),必须调用成员函数完成操作:
立即学习“C++免费学习笔记(深入)”;
-
load():原子读取当前值,可指定内存序(如memory_order_acquire) -
store(val):原子写入,可选内存序(如memory_order_release) -
exchange(val):原子替换并返回旧值(类似“取-存”) -
compare_exchange_weak/strong(expected, desired):CAS(Compare-And-Swap),最常用无锁原语。若当前值等于expected,则设为desired并返回true;否则将当前值写入expected并返回false。推荐用weak版本(可能伪失败,但性能更好),配合循环重试
示例(无锁计数器递增):
std::atomicint old_val = counter.load();
while (!counter.compare_exchange_weak(old_val, old_val + 1)) {
// 若被其他线程抢先修改,old_val已更新,继续重试
}
内存序(memory order)控制可见性与重排
默认使用memory_order_seq_cst(顺序一致性),最安全也最慢。根据场景可降级以提升性能:
-
memory_order_relaxed:仅保证原子性,不约束前后指令重排,适用于计数器、引用计数等无需同步其他数据的场景 -
memory_order_acquire:用于读操作,保证该操作之后的读写不被重排到它前面(获取语义) -
memory_order_release:用于写操作,保证该操作之前的读写不被重排到它后面(释放语义) -
acquire-release配对常用于锁-free队列或信号量实现
错误示例:仅用relaxed实现“生产者-消费者”同步会出问题;正确做法是生产者store(..., release),消费者load(..., acquire)。
常见陷阱与注意事项
-
std::atomic对象本身不可拷贝(禁用拷贝构造/赋值),但可移动(C++20起部分特化支持) - 不支持浮点类型(
std::atomic在标准中未定义,GCC/Clang虽提供但非可移植);可用std::atomic加位转换模拟,但需谨慎处理NaN/符号位 - 复合操作如
fetch_add、fetch_or等对整型和指针有完整支持,比手动CAS更简洁高效 - 不要对
std::atomic取地址传给非原子函数(如printf("%d", &x))——它不是普通变量 - 调试困难:无锁代码一旦出错(如ABA问题、内存序误用),行为难以复现,建议先用锁验证逻辑,再逐步无锁化











