c++oding="utf-8" ?>
std::atomic::wait仅支持bool、char、int等整型特化,要求平台支持futex且需满足is_always_lock_free_v等条件;不支持double、struct或atomic_flag,误用将导致编译错误。

std::atomic::wait 为什么不能直接用在所有原子类型上
因为 std::atomic::wait 只对 std::atomic<bool></bool>、std::atomic<:shared_ptr>></:shared_ptr> 和整型特化(如 std::atomic<int></int>)提供标准支持,且要求底层平台支持 futex 或等效机制(Linux glibc ≥ 2.34,Windows ≥ RS5,macOS 不支持)。你写 std::atomic<double>::wait()</double> 会编译失败——不是语法错,而是该特化根本没声明。
常见误操作是把任意 std::atomic 当作可等待对象,结果卡在 static_assert 错误里,比如:
error: no member named 'wait' in 'std::atomic<double>'</double>
- 只对
bool、char、int、long、long long及其无符号/带符号变体(满足std::is_always_lock_free_v且为 trivially copyable 的整型)有wait/notify_one/notify_all -
std::atomic_flag不支持wait,它连load都是test_and_set语义 - 自定义结构体即使用
std::atomic包装,也无法调用wait,除非显式特化(标准不保证,也不推荐)
std::atomic::wait 的正确使用姿势和必要配套
它不是“等值变化”,而是“等值匹配”:线程挂起当且仅当当前值等于传入的预期值。必须搭配 notify_one 或 notify_all 才能唤醒,且通知方和等待方需操作同一内存位置(即同一个 std::atomic 实例)。
典型安全用法:
std::atomic<int> flag{0};
// 等待 flag 变成 1
int expected = 0;
while (flag.load() != 1) {
flag.wait(expected); // 挂起直到 flag != expected
expected = flag.load(); // 更新预期值,避免 ABA 导致假醒漏判
}</int>
- 必须循环检查条件(spurious wakeup 是允许的),不能只调一次
wait -
expected必须是局部变量,且每次wait返回后立即更新为最新值 - 通知端必须用
flag.store(1, std::memory_order_relaxed)+flag.notify_one(),不能只改值不通知 - 通知和等待的 memory order 不影响
wait语义,但store和load的顺序会影响逻辑正确性
性能陷阱:wait/notify 不等于 condition_variable,别混用场景
std::atomic::wait 是无锁、内核态休眠级等待,比 std::condition_variable 更轻量,但代价是功能受限:无法带 predicate 等待、无法超时、无法广播到非原子变量关联的线程。
- 如果需要等待“某个 struct 字段变化”,不要试图用
std::atomic<mystruct></mystruct>—— 它不支持wait,改用std::mutex+std::condition_variable - 如果要等超时,
std::atomic::wait没有 timeout 版本,得自己结合std::this_thread::sleep_for轮询(牺牲性能)或换用std::condition_variable::wait_for - 频繁短时等待(如自旋几微秒)反而比
wait更快,因为系统调用开销约 100–500 ns;wait适合毫秒级以上阻塞
跨平台兼容性和编译开关注意事项
即使代码语法正确,std::atomic::wait 在 macOS 上始终不可用(Clang/libc++ 未实现),GCC 12+ / MSVC 19.30+ 才开始稳定支持。编译期需显式检查:
#if __cpp_lib_atomic_wait >= 201907L
flag.wait(expected);
#else
while (flag.load() != target) std::this_thread::yield();
#endif
- 依赖
__cpp_lib_atomic_wait宏,不是编译器版本号 - Linux 上需 glibc ≥ 2.34(Ubuntu 22.04 默认搭载,20.04 需手动升级)
- 静态链接时若 glibc 版本不足,运行时会 fallback 到忙等待(不报错但失去性能优势)
- 启用
-D_GLIBCXX_CONCEPTS或 C++20 模式不一定自动开启 wait 支持,必须确认标准库实际实现
真正难的是判断“该不该用”——它快,但只快在特定负载、特定平台、特定数据类型上。多数业务逻辑里,condition_variable 更稳妥;只有高频、低延迟、纯整型信号场景才值得引入 atomic::wait 并处理这些边界。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











