std::atomic 禁止拷贝构造和赋值以保障原子性,必须用 load/store 或 fetch_add/compare_exchange 等原子操作;compare_exchange_weak 因伪失败更高效,推荐循环使用;内存序需按需选择,错用易致数据竞争;T 需 trivially copyable 且尺寸适配,否则退化为加锁。
因为 std::atomic 禁止了拷贝构造和拷贝赋值操作符,这是为保证原子性不被意外破坏。试图写 std::atomic 或 auto c = a; 会触发编译错误:use of deleted function。
.load() 读取当前值(可指定内存序).store(x) 写入新值(同样支持内存序).fetch_ad
d()、.compare_exchange_weak() 等原子成员函数两者都实现 CAS(Compare-and-Swap),但 compare_exchange_weak 允许伪失败(spurious failure):即使预期值匹配,也可能返回 false。这在某些平台(如 x86 上少见,ARM 上较常见)由底层指令限制导致。
weak 版本通常性能更好,推荐作为默认选择strong 版本保证“值不匹配才失败”,适合不能容忍重试逻辑的场景(如单次尝试关键路径)std::atomiccounter{0}; int expected = counter.load(); do { int desired = expected + 1; } while (!counter.compare_exchange_weak(expected, desired));
省略内存序参数(如只写 a.store(42))等价于 a.store(42, std::memory_order_seq_cst),即最强一致性。但多数场景不需要这么重的同步开销。
std::memory_order_relaxed:仅保证原子性,不约束前后内存访问顺序 —— 计数器、标志位常用std::memory_order_acquire:用于读操作,确保之后的读/写不被重排到它前面std::memory_order_release:用于写操作,确保之前的读/写不被重排到它后面错用内存序不会报错,但可能引发极难复现的数据竞争 —— 比如把 relaxed 误用于需同步的 flag 变量,会导致另一线程看到“部分初始化”的对象。
并非所有类型都能套 std::atomic。编译期会检查 T 是否为 trivially copyable,且大小不能超过平台支持的原子指令宽度(通常 ≤ 16 字节,x86-64 下一般 ≤ 8 字节)。
int、long long、指针)基本都 OKstd::is_trivially_copyable_v 且不含虚函数、非平凡构造/析构时,才可能被接受static_assert(std::atomic::is_always_lock_free) 显式校验无锁编程真正的门槛不在语法,而在对共享状态变更边界的精确刻画。一个 std::atomic_flag 能安全自旋,但若把它和非原子字段混在同一缓存行里,就可能因 false sharing 拖垮性能 —— 这类问题不会报错,只会让多核跑得比单核还慢。