C++中线程等待时如何通知调度器切换至下一个线程?
多线程等待优化:替代忙等+短睡眠的最佳方案
你当前用的while(!finished) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); }属于忙等+主动让出时间片的方式,缺点很明显:频繁唤醒线程会浪费CPU资源,而且1ms的间隔会导致响应延迟,没法做到结果就绪时即时唤醒。
下面是几种更优的方案,完全符合你“通知调度器当前线程无事可做,切换至下一个线程”的需求:
1. 标准方案:std::condition_variable(推荐)
这是C++标准库专为线程间通知设计的工具,等待线程会进入阻塞状态(完全不占用CPU),直到被其他线程主动通知,调度器会自动切换到其他就绪线程。
代码示例:
#include <condition_variable> #include <mutex> // 全局/类成员变量(确保所有线程可见) std::mutex mtx; std::condition_variable cv; bool finished = false; // 等待结果的线程代码 void waiting_thread() { // 用unique_lock管理互斥量,wait会自动释放/重新获取锁 std::unique_lock<std::mutex> lock(mtx); // 带谓词的wait,避免系统虚假唤醒 cv.wait(lock, []{ return finished; }); // 到这里说明finished已经为true,可继续执行后续逻辑 } // 完成任务的线程代码 void worker_thread() { // 执行任务逻辑... // 更新状态并通知等待线程 std::lock_guard<std::mutex> lock(mtx); finished = true; cv.notify_one(); // 如果多个线程等待,用notify_all() }
关键说明:
cv.wait()会自动释放互斥量,然后挂起当前线程,直到被notify_one()/notify_all()唤醒。- 带谓词的
wait会在唤醒后重新检查条件,避免系统虚假唤醒(无理由的唤醒)。 - 修改
finished时必须加锁,确保线程间状态可见性,避免竞态条件。
2. 简洁方案:std::future + std::promise
如果你的场景是一对一等待某个任务完成,可以用std::future和std::promise,不需要手动管理互斥量和条件变量,代码更简洁。
代码示例:
#include <future> #include <thread> void waiting_thread(std::future<void>& fut) { fut.wait(); // 线程挂起,直到promise被设置 // 任务完成,继续执行 } void worker_thread(std::promise<void>& prom) { // 执行任务逻辑... prom.set_value(); // 通知等待线程任务完成 } // 主线程中初始化 std::promise<void> task_prom; std::future<void> task_fut = task_prom.get_future(); std::thread t1(waiting_thread, std::ref(task_fut)); std::thread t2(worker_thread, std::ref(task_prom));
方案对比
- 原sleep循环:线程定期唤醒,浪费CPU,响应延迟。
- 条件变量:通用场景,支持多线程等待,无CPU浪费,即时响应。
- future/promise:适合一对一等待,代码更简洁,无需手动锁管理。
内容的提问来源于stack exchange,提问作者Thomas
相关产品推荐
相关产品推荐

