std::condition_variable的使用说明(详细解释和使用示例)
概述
std::condition_variable
是 C++ 标准库中用于线程间通信的同步原语。它允许一个或多个线程等待某个条件为真。通常与 std::mutex
一起使用,std::condition_variable
提供了两种主要的等待方式:wait
和 wait_for
。
使用说明
- 初始化:
std::condition_variable
通常作为类的成员变量进行初始化。 - 等待:使用
wait
或wait_for
方法来阻塞当前线程,直到条件满足。 - 通知:使用
notify_one
或notify_all
方法来唤醒等待的线程。
关键方法
-
void wait(std::unique_lock<std::mutex>& lock);
- 使当前线程阻塞,直到条件变量被通知。
- 调用
wait
之前,必须先对std::mutex
进行上锁,并将锁对象传递给wait
方法。 - 当线程被唤醒时,它会自动重新获取锁。
-
template<class Rep, class Period> std::cv_status wait_for(std::unique_lock<std::mutex>& lock, const std::chrono::duration<Rep, Period>& rel_time);
- 使当前线程阻塞指定的时间长度,或者直到条件变量被通知。
- 如果在指定的时间内没有被通知,则返回
std::cv_status::timeout
。
-
void notify_one();
- 唤醒一个正在等待的线程。
- 如果有多个线程在等待,选择哪个线程被唤醒是不可预测的。
-
void notify_all();
- 唤醒所有正在等待的线程。
使用示例
下面是一个简单的示例,展示了如何使用 std::condition_variable
来实现线程间的同步。这个例子中,主线程等待子线程完成某个任务。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>class Task {
public:void execute() {std::unique_lock<std::mutex> lock(mutex_);std::cout << "模拟一个耗时任务,开始!" << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "模拟一个耗时任务,结束!" << std::endl;status_ = true;// 通知等待的线程cv_.notify_one();}void waitUntilCompleted() {std::unique_lock<std::mutex> lock(mutex_);std::cout << "使用 wait 来等待任务完成!" << std::endl;cv_.wait(lock, [this]{ return status_; });// 当 wait 返回时,说明 status_ 为 truestd::cout << "任务已完成!" << std::endl;}private:std::mutex mutex_;std::condition_variable cv_;bool status_ = false;
};int main() {Task task;// 启动一个新线程执行任务std::thread worker([&task](){ task.execute(); });// 主线程等待任务完成task.waitUntilCompleted();std::cout << "等待子线程结束!" << std::endl;worker.join();std::cout << "子线程已结束!" << std::endl;return 0;
}
说明
execute
方法:模拟了一个耗时任务。在任务完成后,设置status_
为true
,并使用notify_one
通知等待的线程。waitUntilCompleted
方法:使用wait
方法来等待status_
变为true
。wait
方法的第一个参数是一个std::unique_lock<std::mutex>
,第二个参数是一个 lambda 表达式,该表达式返回一个布尔值,表示等待的条件。main
函数:创建了一个Task
对象,并启动了一个子线程来执行任务。主线程调用waitUntilCompleted
方法来等待任务完成,然后等待子线程结束。
在这个示例中,std::condition_variable
被用来实现在任务完成时通知等待的线程。这样可以有效地避免 busy-waiting(忙等待),提高程序的性能和响应性。