std::condition_variable
是 C++ 标准库中的一个类,它用于线程间的同步。std::condition_variable
允许一个或多个线程等待某个条件的发生,而其他线程可以唤醒等待的线程。它通常与 std::unique_lock<std::mutex>
一起使用,以保护共享数据并同步线程。
主要成员函数
-
wait
:- 使调用线程阻塞,直到另一个线程调用同一个条件变量的
notify_one
或notify_all
函数。
- 使调用线程阻塞,直到另一个线程调用同一个条件变量的
-
wait_for
:- 使调用线程阻塞,直到另一个线程调用
notify_one
或notify_all
,或者超时发生。
- 使调用线程阻塞,直到另一个线程调用
-
wait_until
:- 使调用线程阻塞,直到另一个线程调用
notify_one
或notify_all
,或者到达指定的时间点。
- 使调用线程阻塞,直到另一个线程调用
-
notify_one
:- 唤醒等待此条件变量的一个线程。
-
notify_all
:- 唤醒等待此条件变量的所有线程。
使用条件变量的步骤
-
初始化条件变量和互斥锁:
- 创建一个
std::condition_variable
对象和一个std::mutex
对象。
- 创建一个
-
线程等待条件:
- 线程锁定互斥锁,并在条件变量上调用
wait
、wait_for
或wait_until
函数,进入等待状态。
- 线程锁定互斥锁,并在条件变量上调用
-
条件满足时唤醒线程:
- 当条件满足时,另一个线程锁定相同的互斥锁,并调用
notify_one
或notify_all
来唤醒等待的线程。
- 当条件满足时,另一个线程锁定相同的互斥锁,并调用
示例代码
以下是一个使用 std::condition_variable
的示例:
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void print_id(int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) { // 只有当 ready 为 true 时,线程才会继续执行
cv.wait(lck);
}
// 执行线程的其余部分...
std::cout << "Thread " << id << '\n';
}
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all(); // 唤醒所有等待的线程
}
int main() {
std::thread threads[10];
// 启动 10 个线程
for (int i = 0; i < 10; ++i)
threads[i] = std::thread(print_id, i);
std::cout << "10 threads ready to race...\n";
go(); // 通知线程开始执行
for (auto& th : threads) th.join(); // 等待所有线程完成
return 0;
}
解释
-
初始化条件变量和互斥锁:
std::mutex mtx; std::condition_variable cv; bool ready = false;
-
线程等待条件:
void print_id(int id) { std::unique_lock<std::mutex> lck(mtx); while (!ready) { // 只有当 ready 为 true 时,线程才会继续执行 cv.wait(lck); } // 执行线程的其余部分... std::cout << "Thread " << id << '\n'; }
-
条件满足时唤醒线程:
void go() { std::unique_lock<std::mutex> lck(mtx); ready = true; cv.notify_all(); // 唤醒所有等待的线程 }
-
主函数:
int main() { std::thread threads[10]; // 启动 10 个线程 for (int i = 0; i < 10; ++i) threads[i] = std::thread(print_id, i); std::cout << "10 threads ready to race...\n"; go(); // 通知线程开始执行 for (auto& th : threads) th.join(); // 等待所有线程完成 return 0; }