std::atomic::wait比while循环更高效,因为它使线程进入内核级休眠(如futex_wait),避免CPU空转;但仅当平台支持(Linux≥5.1+glibc≥2.34或Windows 10 1809+)、类型为整型/指针、且值严格匹配时才生效,否则退化为自旋或报错。

std::atomic::wait 为什么比 while 循环更高效
因为 std::atomic::wait 让线程进入内核级休眠(类似 futex_wait),而不是在用户态空转。CPU 不再消耗周期,操作系统能调度其他任务,唤醒由内核在原子值变更时精确触发——前提是目标平台支持 std::atomic 的等待/通知机制(Linux ≥ 5.1 + glibc ≥ 2.34,或 Windows 10 1809+)。
常见错误是直接在不支持的环境(如旧版 macOS、某些嵌入式 libc++)下调用 wait,会抛出 std::system_error 并提示 operation_not_supported。运行前务必检查:
if (!std::atomic<int>{}.is_always_lock_free) { /* 可能不支持 wait */ }
如何正确调用 std::atomic::wait 和 notify_one
wait 必须配合 notify_one 或 notify_all 使用,且等待值必须与当前原子值一致(否则立即返回)。典型模式是:先读取当前值,再以该值为参数调用 wait。
- 不能传入一个“期望值”然后等它变成这个值——
wait等的是“当前值等于你传入的值”这一瞬时状态 - 必须在
wait前获取当前值,例如:auto expected = flag.load(); flag.wait(expected); -
notify_one必须在修改原子变量后调用,且修改和通知之间不能有竞态;推荐用store(new_val, std::memory_order_release)+notify_one() - 多个线程调用
wait时,notify_one只唤醒一个,notify_all唤醒全部——但唤醒后仍需重新检查条件,防止虚假唤醒
std::atomic::wait 在哪些类型上可用
仅对整型(int、long、std::size_t 等)和指针类型支持 wait/notify;bool 和自定义结构体不支持(即使 is_always_lock_free 为 true)。
立即学习“C++免费学习笔记(深入)”;
常见误用:std::atomic<bool> ready{false}; ready.wait(true); —— 编译失败。解决办法是改用 std::atomic<int> 或 std::atomic<char> 模拟布尔逻辑:
std::atomic<int> ready{0};
// 等待就绪
while (ready.load() == 0) {
ready.wait(0); // ✅ 合法
}
// 设置就绪
ready.store(1, std::memory_order_release);
ready.notify_one();wait 调用前必须加内存序判断吗
不需要显式加内存序,wait 内部已隐含 std::memory_order_acquire 语义(唤醒后读到的通知前写入)。但你仍需保证通知方使用匹配的释放序(store(..., std::memory_order_release)),否则可能读到陈旧值。
容易忽略的点:
-
wait返回后,原子变量的值**不一定仍是传入的 expected 值**(可能已被其他线程改写),所以必须循环检查实际条件 - 没有超时版本的
wait(C++20 标准未提供),如需超时,得回退到std::this_thread::sleep_for+ 自旋,或封装成带超时的 helper - 若原子变量被频繁修改,
wait可能被反复唤醒又立刻返回(因值已变),此时不如直接自旋——需实测权衡
真正关键的不是“怎么写”,而是确认你的部署环境是否启用 futex 支持,并验证 notify 是否总在 store 之后、无遗漏路径。漏掉一次 notify,就有一个线程永远卡在 wait 里。



















