std::condition_variable
的notify_all()
方法用于唤醒所有等待该条件变量的线程。
这与notify_one()
不同,后者只唤醒一个等待的线程。使用notify_all()
是在某些条件变化对所有等待线程都是有意义时的理想选择,
例如,在共享资源状态发生变化时,可能希望所有等待该资源的线程都能重新检查条件并继续执行。
使用场景
notify_all()
常用于以下场景:
- 当共享数据的状态变化可能影响到所有等待线程时。
- 当程序逻辑要求在条件满足时所有线程都应该被唤醒继续执行。
使用示例
使用std::condition_variable
实现简单的线程池结束通知
以下示例展示如何使用notify_all()
在一个简化的线程池结束时通知所有工作线程停止工作:
#include <iostream>
#include <vector>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <atomic>
std::mutex mtx; // 互斥量,保护条件变量
std::condition_variable cv; // 条件变量
std::atomic<bool> done(false); // 原子变量,指示工作是否完成
void worker_thread(int id) {
std::unique_lock<std::mutex> lock(mtx);
while (!done.load()) {
cv.wait(lock, [] { return done.load(); }); // 等待done变为true
std::cout << "Worker thread " << id << " is stopping." << std::endl;
}
}
int main() {
const int num_threads = 5;
std::vector<std::thread> threads;
// 创建多个工作线程
for (int i = 0; i < num_threads; ++i) {
threads.emplace_back(worker_thread, i);
}
// 模拟主线程中的工作
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟工作
done = true; // 标记工作完成
cv.notify_all(); // 通知所有工作线程
// 等待所有线程完成
for (auto& t : threads) {
t.join();
}
return 0;
}
输出:
Worker thread 1 is stopping.
Worker thread 2 is stopping.
Worker thread 4 is stopping.
Worker thread 0 is stopping.
Worker thread 3 is stopping.
在这个示例中,我们有几个工作线程,它们在done
变量为false
时会一直等待。
当主线程的模拟工作完成后,它将done
设置为true
并调用cv.notify_all()
,这导致所有等待的工作线程被唤醒。每个工作线程检查done
变量,发现它为true
,于是输出消息并退出。
注意事项
- 使用
notify_all()
时需要确保所有等待线程都应该被唤醒。过度使用notify_all()
可能会导致性能问题,因为它会唤醒所有等待线程,即使有些线程可能并不需要被唤醒。 - 在调用
notify_one()
或notify_all()
时不需要持有互斥量锁,但是修改条件变量所依赖的变量时(比如示例中的done
变量)通常需要加锁,以保证数据的一致性和线程安全。
通过合理使用notify_all()
,可以有效地控制多线程程序中的线程同步和通信,优化程序逻辑和性能。