条件变量未正确使用会导致逻辑随机失效:必须用已上锁的unique_lock调用wait();需用while循环或带谓词的wait防虚假唤醒;notify必须在锁内与状态更新同步;wait_for/untill返回值不可忽略;条件状态须由独立变量+互斥锁维护。

条件变量没正确 wait() 是 C++ 多线程里最隐蔽、最容易复现又最难 debug 的 Bug 之一——它不 crash,不报错,但程序逻辑随机失效,比如消费者永远等不到通知、生产者发了通知却没人收、或者线程卡在 wait() 里不动。根本原因不是“忘了调用”,而是调用方式违反了条件变量的语义契约。
condition_variable::wait() 前必须持有对应 mutex
这是硬性要求,不是建议。如果传给 wait() 的 std::unique_lock 没上锁(比如构造时用了 std::defer_lock 但忘了 lock()),行为是未定义的:可能立即 crash,也可能静默失败,还可能在某些编译器/平台下看似正常,换环境就崩。
- 错误写法:
std::unique_lock<:mutex> lk(mtx, std::defer_lock); cv.wait(lk, []{ return ready; });</:mutex>——lk根本没锁,wait()会直接 abort 或 hang - 正确写法:
std::unique_lock<:mutex> lk(mtx); cv.wait(lk, []{ return ready; });</:mutex> - 更安全的写法:始终用
std::lock_guard配合wait()的重载变体(需注意它内部会临时释放锁)
用 if 判断条件 + wait 导致虚假唤醒后逻辑错乱
std::condition_variable 允许虚假唤醒(spurious wakeup),即没有 notify 也返回。如果你只用 if (ready) { /* do work */ } + wait(),一旦发生虚假唤醒,ready 仍为 false,但线程已跳出等待,后续操作大概率读到脏数据或触发断言失败。
- 典型错误:
if (!ready) cv.wait(lk); do_work(); - 必须改成循环:
while (!ready) cv.wait(lk); do_work();或直接用带谓词的wait(lk, []{ return ready; })—— 这个重载内部就是 while 循环 - 注意:谓词函数必须是无副作用的纯判断,不能在里面修改
ready或其他共享状态
notify_one / notify_all 调用时机错位,通知被丢弃
条件变量的通知不是“消息队列”,它只唤醒当前正在 wait() 的线程。如果 notify 发生在 wait() 之前(比如生产者先设 ready = true 再 notify,而消费者还没开始 wait),这次通知就彻底丢失,消费者将无限等待。
- 关键原则:所有状态变更(如
ready = true)和notify必须在同一个std::unique_lock保护下完成 - 正确顺序:
lk.lock(); ready = true; cv.notify_one(); lk.unlock(); - 反模式:
ready = true; cv.notify_one();(没锁)或ready = true;(解锁后才 notify) - 如果担心竞争,可把状态检查和 wait 合并在一个锁区内,但通常没必要——只要 notify 在锁内,就能保证对 wait 线程可见
wait_for / wait_until 返回值被忽略,超时逻辑失效
wait_for() 和 wait_until() 返回 std::cv_status::no_timeout 或 std::cv_status::timeout。如果只调用不检查返回值,等于放弃了超时机制,线程仍可能卡死。
- 错误:
cv.wait_for(lk, 100ms); // 不管返回啥,直接往下走 - 正确:
if (cv.wait_for(lk, 100ms) == std::cv_status::timeout) { /* 处理超时 */ } else { /* 条件满足,继续 */ } - 注意:超时返回后,谓词不一定为 true,必须重新检查状态(比如再判断
ready),不能假设“没超时就一定 ready”
最常被忽略的一点是:条件变量本身不保存状态,它只是协调工具。所有业务逻辑依赖的“条件”(比如 ready、队列非空、缓冲区有数据)必须由你用独立的变量+互斥锁来维护。把希望寄托在 notify 不丢、wait 不假醒、时间片不调度错位,迟早出问题。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











