std::condition_variable 必须与 std::mutex 配合使用,通过原子地释放锁并等待来避免 cpu 空转,需用 lambda 循环检查条件防虚假唤醒;notify 须在持有锁时调用,且不能早于 wait;而 std::future/std::promise 更适合一次性结果传递,不支持多次信号。

用 std::condition_variable 配合 std::mutex 是最常用且安全的做法
直接裸调用 sleep 或轮询 volatile bool 会导致 CPU 空转或响应延迟,std::condition_variable 才是标准库提供的“挂起等待 + 唤醒”机制。它必须和 std::mutex 搭配使用,不能单独存在——这是很多人写错的第一步。
关键点在于:等待线程必须在锁住互斥量后检查条件、然后原子地释放锁并进入等待;通知线程必须在修改共享状态后、仍持有锁时调用 notify_one() 或 notify_all()。
-
wait()的 lambda 参数不是可选的——它用于防止虚假唤醒,必须重新检查条件是否真正满足 - 不要用
notify_one()去唤醒可能还没开始等待的线程(比如通知发生在等待之前),否则信号会丢失;此时应配合初始化标志位或改用std::atomic<bool></bool>做初始状态兜底 -
std::condition_variable只保证唤醒,不保证唤醒后条件一定成立,所以循环检查必不可少
为什么不用 std::future / std::promise?什么场景下它更合适
如果只是“等一个结果”,比如另一个线程算完一个值再继续,std::promise + std::future 更简洁、无锁、语义清晰。但它是一次性的:std::promise::set_value() 只能调用一次,重复调用会抛 std::future_error(错误码为 future_errc::promise_already_satisfied)。
典型适用场景:std::thread 启动后立即返回 std::future,主线程调用 wait() 或 get() 阻塞等待;或者用 std::async 自动生成。
-
std::future::wait()不取值,只阻塞;get()会移动获取结果,之后再次调用会抛std::future_error(future_errc::no_state) - 跨线程传递异常也靠它:
std::promise::set_exception()能让get()抛出原异常,比手动编码错误码更自然 - 但它无法处理“多次信号”或“状态切换”类需求(比如暂停/恢复),这时候还是得回到
condition_variable
容易被忽略的死锁与初始化顺序问题
常见死锁发生在:等待线程已加锁并调用 wait(),但通知线程因未获取到同一把锁而卡住——本质是锁粒度或作用域没对齐。更隐蔽的是对象生命周期问题:std::condition_variable 和 std::mutex 必须在线程结束前保持有效,若它们是局部变量或被提前析构,wait() 可能访问已释放内存。
- 避免在 lambda 捕获中隐式持有
this并在线程里访问已销毁对象——尤其在类成员函数启动线程时 - 如果用
std::shared_ptr管理共享状态,确保std::condition_variable和std::mutex也在其管理范围内,或至少比所有等待线程活得久 - Linux 下可用
pthread_condattr_setclock()切换为CLOCK_MONOTONIC避免系统时间调整影响超时逻辑,但 C++ 标准库不暴露该接口,需自行封装或接受wait_for()基于系统时钟的限制
Windows 上 WaitForSingleObject 能替代吗?
可以,但不推荐混用。Win32 的 WaitForSingleObject 配合 CreateEvent 确实能实现类似功能,而且支持内核级等待、可等待多个句柄、还能设超时精度达毫秒级。但它把代码绑死在 Windows,且与 C++ 标准线程模型脱节——比如你不能用 std::thread::joinable() 安全判断,也不能和 std::future 互通。
- 若项目已重度依赖 Win32 API(如 GUI 程序),用事件对象没问题;但新项目优先走标准库
-
SetEvent()是发信号,ResetEvent()手动重置,而std::condition_variable的唤醒是自动“消费型”的,无需重置 - 跨平台构建时,混用会导致编译失败或运行时未定义行为,特别是
std::thread对象和 Win32 句柄之间没有生命周期关联
while 循环检查,少一个生产环境超时故障。C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











