std::condition_variable必须与std::mutex配合使用,且仅接受std::unique_lock;等待需用带谓词的wait()防虚假唤醒,notify选择取决于语义,生产环境应优先使用带超时的wait_for()/wait_until()。

std::condition_variable必须和std::mutex一起用
单独声明std::condition_variable却不用锁,线程会直接崩溃或触发未定义行为。它不管理共享状态,只负责“等待”和“通知”,状态保护必须由外部std::mutex承担。
常见错误是写成:cv.wait()前没加锁,或者用std::mutex以外的锁(比如std::shared_mutex)——std::condition_variable只接受std::unique_lock<:mutex></:mutex>。
- 必须用
std::unique_lock<:mutex></:mutex>传入wait(),不能用std::lock_guard -
std::unique_lock构造时要传入已上锁的std::mutex,或让它自动加锁 - 条件检查必须在
wait()的lambda里做,且该lambda返回true才退出等待
wait()里的predicate不能省略
写cv.wait(lock)(无谓词版本)极容易导致虚假唤醒后逻辑错乱。POSIX和C++标准都允许wait()在没被notify_one()或notify_all()调用时返回,这叫spurious wakeup。
正确做法是把“是否该继续执行”的判断逻辑放进lambda:
立即学习“C++免费学习笔记(深入)”;
cv.wait(lock, [&ready]() { return ready; });
这个lambda会在每次从等待中醒来时重新求值。如果返回false,它会自动重新进入等待并再次释放锁;如果返回true,才继续往下走。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 别把
ready改成ready == true——冗余且易出错 - lambda捕获要用
[&]或显式按引用捕获,确保看到最新值 - 变量
ready本身必须是std::atomic<bool></bool>或受同一互斥锁保护,否则读写竞争
notify_one()和notify_all()的区别很实际
用notify_one()还是notify_all()不是风格选择,而是语义决定的:前者只唤醒一个等待线程,后者唤醒所有。选错会导致死锁或资源浪费。
典型场景:
- 生产者-消费者中,一个新任务到来,只需唤醒一个空闲消费者 → 用
notify_one() - 状态变更影响所有等待者(如关闭标志置位、全局配置更新)→ 用
notify_all() - 多个线程等同一个条件但各自处理不同数据,用
notify_one()更高效;若条件满足后所有线程都要重试检查,就得用notify_all()
注意:notify_*调用本身不要求持有锁,但通常放在修改共享状态的临界区末尾,保证等待线程醒来时看到一致状态。
别忘了wait_for()和wait_until()的超时处理
没有超时的wait()可能永远卡住——比如通知丢失、逻辑缺陷、或对方线程提前退出。生产代码几乎都应该用带超时的版本。
wait_for()适合固定等待时间(如“最多等100ms”),wait_until()适合绝对时间点(如“等到某个deadline”):
if (cv.wait_for(lock, 100ms, [&ready]() { return ready; })) {
// 真正被notify唤醒
} else {
// 超时,需检查是否仍需等待或放弃
}
- 超时返回
false不代表失败,只是“没等到”,业务逻辑要自己判断下一步 - 超时时间单位用
std::chrono类型,别传整数毫秒——cv.wait_for(lock, 100)会编译不过 - 即使超时,lambda仍会被执行一次,所以条件检查逻辑不能有副作用
真正麻烦的是多条件组合等待、嵌套锁、或需要响应中断的场景——这些std::condition_variable不解决,得靠std::stop_token或自定义信号机制补足。

















