在 C++ 中,条件变量的等待操作主要通过std::condition_variable类来实现,其等待操作涉及到与互斥锁的配合使用,以下是详细的实现过程:
- 包含必要的头文件
首先需要包含<condition_variable>和头文件,因为条件变量std::condition_variable的使用需要与互斥锁(如std::mutex)协同工作,同时还可能用到std::unique_lock来管理互斥锁的获取和释放。
cpp
复制
#include <condition_variable>
#include <mutex>
- 定义互斥锁和条件变量
在代码中定义一个互斥锁和一个条件变量,例如:
cpp
复制
std::mutex mutex_g;
std::condition_variable condition_g;
这里的mutex_g用于保护共享资源以及条件变量相关操作的互斥访问,condition_g则是用于实现线程等待特定条件满足的机制。
3. 获取互斥锁并检查条件
线程在执行等待操作之前,需要先获取互斥锁,以确保对共享资源和条件变量相关操作的独占访问权。这通常通过std::unique_lock来实现,它在构造函数中获取互斥锁,并在析构函数中自动释放互斥锁。
例如,假设有一个共享资源shared_resource_g和一个用于标识条件是否满足的标志condition_met,线程函数如下:
cpp
复制
// 用于标识条件是否满足的标志
bool condition_met = false;
// 共享资源,这里是一个简单的整数变量
int shared_resource_g = 0;
// 线程函数,用于等待条件满足
void wait_for_condition() {
// 获取互斥锁
std::unique_lock<std::mutex> lock(mutex_g);
// 检查条件是否满足
while (!condition_met) {
// 如果条件不满足,将进入条件变量的等待操作
}
// 条件满足后,可对共享资源进行后续操作
// 这里省略具体操作,仅示意
std::cout << "Condition met, can access shared resource: " << shared_resource_g << std::endl;
}
在上述代码中,线程首先通过std::unique_lockstd::mutex lock(mutex_g);获取互斥锁,然后在while循环中检查条件condition_met是否满足。如果不满足,就会进入条件变量的等待操作。
4. 执行条件变量的等待操作
当条件不满足时,线程会执行条件变量的等待操作,即调用std::condition_variable的wait方法。wait方法有两种常见的重载形式:
形式一:
cpp
复制
void wait(std::unique_lock<std::mutex>& lock);
这种形式只接受一个std::unique_lock类型的参数,它会自动释放所获取的互斥锁,使线程进入等待状态,并将线程挂起,直到被其他线程通过notify_one或notify_all方法唤醒。被唤醒后,线程会自动重新获取互斥锁,然后继续执行后续代码(也就是再次检查条件是否满足等)。
例如,在上述代码的while循环中添加等待操作如下:
cpp
复制
while (!condition_met) {
condition_g.wait(lock);
}
形式二:
cpp
复制
template <typename Predicate>
void wait(std::unique_lock<std::mutex>& lock, Predicate pred);
这种重载形式除了接受std::unique_lock参数外,还接受一个可调用对象(如函数、函数指针、lambda 表达式等)作为参数,这个可调用对象用于判断条件是否满足。它的工作原理是:先判断可调用对象返回的结果,如果结果为true,则说明条件满足,线程不会进入等待状态,直接继续执行后续代码;如果结果为false,则会像第一种形式一样,释放互斥锁进入等待状态,被唤醒后重新获取互斥锁并再次调用可调用对象判断条件是否满足,只有当可调用对象返回true时,线程才会继续执行后续代码。
例如,使用 lambda 表达式作为可调用对象的示例如下:
cpp
复制
while (!condition_met) {
condition_g.wait(lock, []{ return condition_met; });
}
在这个示例中,lambda 表达式[]{ return condition_met; }用于判断条件是否满足,当条件满足时(即condition_met为true),线程不会进入等待状态,直接继续执行后续代码。
通过以上步骤,C++ 中的条件变量实现了线程等待特定条件满足的操作,并且在等待过程中合理地处理了互斥锁的获取和释放,以确保共享资源的安全访问以及条件变量操作的正确性。