std::condition_variable必须与std::mutex配合使用,仅靠其自身无法保证线程同步;它不维护计数、不缓存通知,依赖外部互斥锁和共享状态实现正确等待/唤醒逻辑。

std::condition_variable必须和std::mutex一起用
单独调用wait()会直接崩溃,因为内部依赖互斥量做原子性检查。它不是信号量,也不维护内部计数——只负责“挂起等待”和“被唤醒”,一切同步逻辑得靠外部std::mutex和共享状态变量来保障。
常见错误是只锁了std::mutex但没在wait()前检查条件,导致虚假唤醒后直接往下走;或者忘了在通知前加锁,造成notify_one()/notify_all()执行时条件已变更,接收方永远等不到。
- 必须用
std::unique_lock<:mutex></:mutex>构造,不能用std::lock_guard(后者不支持wait()需要的解锁/重锁语义) -
wait()函数内部会自动释放锁、挂起线程;被唤醒后自动重新获取锁,再返回 - 永远用带谓词的重载:
cv.wait(lock, [&]{ return ready; });,避免手动写while(!ready) cv.wait(lock);这种易漏检查的写法
notify_one()和notify_all()选哪个?
取决于你期望唤醒几个消费者。如果只有一个任务在等,用notify_one()更轻量;如果多个线程阻塞在同一个std::condition_variable上,且每个都该处理一个独立任务(比如线程池取任务),那就必须用notify_all()——但要注意:不是所有被唤醒的线程都能拿到任务,多数会再次进入等待,所以仍需配合条件检查。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
-
notify_one()不保证唤醒“最先等待”的线程,调度由系统决定 - 调用
notify_*时,std::mutex可以已解锁,也可以还锁着——但若此时有线程正wait()中,唤醒动作是即时的;若没有线程在等,通知就丢失(不会排队) - 不要在持有锁期间做耗时操作后再
notify,否则唤醒延迟高;通常先更新共享状态、解锁、再notify
典型任务通知模式:生产者-消费者队列
这是最常用场景:一个或多个线程往队列推任务,工作线程从队列取任务执行。关键点在于“队列空”时消费者要等待,“队列非空”时生产者要通知。
std::queue<:function>> tasks;
std::mutex mtx;
std::condition_variable cv;
bool shutdown = false;
<p>// 消费者
while (true) {
std::function<void> task;
{
std::unique_lock<:mutex> lock(mtx);
cv.wait(lock, [&]{ return !tasks.empty() || shutdown; });
if (shutdown && tasks.empty()) break;
task = std::move(tasks.front());
tasks.pop();
}
task();
}</:mutex></void></p>
<p>// 生产者
{
std::unique_lock<:mutex> lock(mtx);
tasks.push([]{ /<em> do work </em>/ });
}
cv.notify_one(); // 或 notify_all(),视情况而定
</:mutex></p></:function>
- 退出条件(如
shutdown)必须和业务条件一起放进wait()谓词里,否则可能错过终止信号 - 出队操作必须在锁内完成,避免其他线程并发修改队列
- 通知放在锁外,减少临界区长度;但如果通知逻辑依赖锁保护的状态,就得锁内通知
为什么有时wait()没被唤醒?
最常见原因是:通知发生在等待之前,而std::condition_variable不缓存通知。比如生产者先notify_one(),消费者后wait(),那这次通知就丢了。
- 解决办法:用“状态+通知”组合。始终先改共享状态(如
ready = true),再notify;消费者wait()时检查该状态 - 别依赖
notify的时序,它只表示“可能有变化”,最终决策权在谓词里 - 调试时可在
wait()前后加日志,确认锁是否正常获取、谓词是否按预期返回true
真正难的是状态设计和边界判断——比如多生产者单消费者下,如何避免重复通知、如何安全关闭队列。这些没法靠std::condition_variable自动解决,得靠代码逻辑兜住。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










