任务唤醒
std::ccondition_variable
核心使用思路
std::condition_variable(条件变量)的核心作用是让一个/多个线程等待某个条件满足,当条件满足时,由其他线程唤醒等待的线程。
关键组合:std::condition_variable + std::mutex + 共享条件(布尔变量/计数器等)。
核心唤醒函数:
notify_one():唤醒一个等待的线程(随机/按调度策略)。notify_all():唤醒所有等待的线程。
完整可运行示例
下面通过一个“生产者-消费者”示例,展示如何唤醒等待的任务:
1 |
|
关键代码解释
等待逻辑(消费者):
1
cv.wait(lock, []() { return !task_queue.empty() || stop_flag; });
wait会先解锁mutex,让线程进入等待状态,释放CPU资源。- 第二个参数是条件判断谓词:只有当谓词返回
true时,线程才会被唤醒并重新加锁;否则会继续等待(避免“虚假唤醒”)。 - 若省略谓词,需手动用
while检查条件:1
2
3while (task_queue.empty() && !stop_flag) {
cv.wait(lock);
}
唤醒逻辑(生产者):
cv.notify_one():唤醒任意一个等待在该条件变量上的线程(适合单消费者/多消费者但只需一个处理的场景)。cv.notify_all():唤醒所有等待的线程(适合多消费者、需要全部处理收尾的场景)。
锁的使用:
- 操作共享资源(
task_queue/stop_flag)时必须加锁(std::lock_guard/std::unique_lock)。 wait要求传入std::unique_lock(因为需要在等待时临时解锁),而lock_guard是不可解锁的,无法用于wait。
- 操作共享资源(
运行前置条件
- 编译器支持 C++11 及以上(
std::condition_variable是 C++11 引入的)。 - 编译命令(以g++为例):注意:必须加
1
2g++ -std=c++11 -pthread condition_variable_demo.cpp -o demo
./demo-pthread链接线程库,否则会报链接错误。
总结
std::condition_variable唤醒任务的核心是notify_one()(唤醒一个)和notify_all()(唤醒所有),需搭配std::mutex和条件判断使用。- 等待时必须用
wait+ 条件谓词(或while循环),避免虚假唤醒导致逻辑错误。 - 操作共享条件/资源时必须加锁,唤醒前建议解锁(提升性能),确保等待线程能立即获取锁。
问题1:wait() 和 wait_for() 的区别?
代码中的条件变量使用
1 | int MpFileManager::workerThread() |
wait 和 wait_for 的区别
1. 等待方式
- wait: 无限期等待,直到条件变量被通知或被虚假唤醒
- wait_for: 有时间限制的等待,在指定时间段内等待,超时后自动返回
2. 超时控制
- wait: 无超时参数,可能永久阻塞
- wait_for: 接收时间间隔参数(如代码中的
std::chrono::seconds(2)),避免无限等待
3. 实际应用
- wait: 适用于必须等待到条件满足的场景
- wait_for: 适用于需要定期检查或避免死锁的场景,代码中每秒检查一次条件
4. 返回时机
- wait: 只在条件满足或被通知时返回
- wait_for: 可能因超时、条件满足或被通知而返回
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 naro!




