std::atomic::wait/notify 是 C++20 轻量级同步机制,依赖 futex 等内核原语实现休眠唤醒;需确保类型支持、状态匹配、正确内存序,并用循环检查避免通知丢失与误判。

一、理解 std::atomic::wait 与 notify 的底层机制
std::atomic::wait 和 std::atomic::notify_one/notify_all 是 C++20 引入的原子等待-通知机制,用于在多个线程间实现轻量级同步,避免自旋轮询开销。该机制依赖于操作系统提供的 futex(Linux)或等效内核原语,在原子值未发生预期变更时使线程进入休眠状态,仅当对应 notify 被调用且条件满足时才被唤醒。
1、确保所用 std::atomic 类型支持 wait 操作,例如 std::atomic
2、调用 wait 前必须保证原子变量处于可等待状态,即其当前值与期望值相等;
3、notify_one 仅唤醒一个正在等待该原子变量的线程,notify_all 则唤醒所有等待线程,但不保证唤醒顺序。
立即学习“C++免费学习笔记(深入)”;
二、使用 std::atomic::wait 实现事件就绪等待
通过将原子变量作为事件标志位,线程可在其变为 true 或特定数值时阻塞等待,从而替代条件变量加互斥锁的经典模式。该方式消除了锁竞争与上下文切换冗余,适用于高频率、低延迟的事件驱动场景。
1、声明一个 std::atomic
2、等待线程执行 event_flag.wait(false),进入等待状态直至 flag 变为 true;
3、触发线程在事件就绪后执行 event_flag.store(true, std::memory_order_release);
4、随后调用 event_flag.notify_one(),唤醒任意一个等待线程;
5、被唤醒线程自动重新检查 event_flag.load(std::memory_order_acquire),确认值已变更后继续执行。
三、避免虚假唤醒与状态检查遗漏
尽管 std::atomic::wait 不像 std::condition_variable 那样存在标准规定的虚假唤醒,但在多通知源或多次 notify 场景下,仍需确保等待逻辑包裹在循环中,防止因 notify 提前发生或值被意外修改导致误判。
1、使用 while 循环包裹 wait 调用,例如 while (flag.load() == expected) flag.wait(expected);
2、每次从 wait 返回后,必须再次 load 当前值并验证是否满足业务条件;
3、若 flag 在 wait 返回前已被其他线程修改为非 expected 值,则 wait 立即返回,此时 必须重新评估条件而非直接执行后续逻辑;
4、避免将 wait 放在 if 语句内而不加循环,否则可能跳过有效状态变更。
四、跨线程通知丢失问题的规避方法
当 notify 在 wait 之前执行,且无其他同步机制时,等待线程将永远阻塞。这是原子等待机制的固有特性,需通过初始化状态或内存序配合加以规避。
1、初始化原子变量为能表达“未就绪”含义的初始值,例如 std::atomic
2、触发线程在修改状态后,必须使用 std::memory_order_release 存储新值,并紧随其后调用 notify;
3、等待线程在调用 wait 前,应先以 std::memory_order_acquire 加载一次当前值,确认尚未就绪;
4、关键原则:notify 必须发生在状态更新之后、且不能早于任何等待线程进入 wait 的时刻;
5、若无法确保时序,可引入 std::atomic_flag 或 std::atomic
五、与 std::condition_variable 的对比迁移策略
在已有基于互斥锁和条件变量的事件通知代码中,迁移到 std::atomic::wait 需重构同步模型,核心是剥离锁依赖并确保状态变更可见性。
1、移除 std::mutex 和 std::unique_lock,删除所有 lock/unlock 调用;
2、将原本保护的 bool 标志替换为 std::atomic
3、将 cond_var.notify_one() 替换为 atomic_var.notify_one(),注意 notify 前必须已完成 store 操作;
4、等待端将 while (cond) { cond_var.wait(lock); } 改为 while (atomic_var.load() == false) { atomic_var.wait(false); };
5、迁移后必须验证所有 store/notify 成对出现,且无 notify 被遗漏或重复调用。


















