目录
condition_variable
简介
std::condition_variable
是C++中用于线程同步的一个类。它通常与std::mutex
一起使用,用于在一个或多个线程中阻塞,直到另一个线程修改了共享变量并通知了condition_variable
。下面是一个例子,演示了如何使用std::condition_variable
来实现线程间的通信:
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
void worker_thread() {
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] { return ready; });
std::cout << "Worker thread is processing data\n";
data += " after processing";
processed = true;
std::cout << "Worker thread signals data processing completed\n";
lk.unlock();
cv.notify_one();
}
int main() {
std::thread worker(worker_thread);
{
std::lock_guard<std::mutex> lk(m);
ready = true;
}
cv.notify_one();
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] { return processed; });
}
std::cout << "Back in main, data = " << data << '\n';
worker.join();
}
在这个例子中,worker_thread
等待ready
变量为true
,然后处理数据并通知主线程。主线程等待processed
变量为true
,然后打印处理后的数据。这个例子展示了std::condition_variable
的基本用法。
成员函数
std::condition_variable
是C++标准库中用于线程同步的类,它提供了以下成员函数:
-
wait
:阻塞当前线程,直到收到通知或超时。void wait(std::unique_lock<std::mutex>& lock, Predicate pred);
这个函数会在持有
std::unique_lock
锁的情况下,释放锁并将线程置于等待状态。当收到通知或超时时,线程会重新获得锁并继续执行。在使用
std::condition_variable
的wait
函数时,可以正确地传递Predicate参数。wait
函数有两个重载版本,其中第二个版本接受一个Predicate参数,用于判断条件是否满足。Predicate是一个可调用对象,通常是一个lambda表达式或者函数对象,用于在等待期间检查条件是否满足。下面是一个示例,演示了如何在
wait
函数中正确地传递Predicate参数:std::condition_variable cv; std::mutex mtx; bool dataReady = false; void threadFunction() { std::unique_lock<std::mutex> lck(mtx); cv.wait(lck, []{ return dataReady; }); // 线程被唤醒后,继续执行其他操作 } void setDataReady() { std::lock_guard<std::mutex> lck(mtx); dataReady = true; cv.notify_one(); }
在这个示例中,
cv.wait
函数的第二个参数是一个lambda表达式[]{ return dataReady; }
,用于检查条件dataReady
是否为true。当条件满足时,线程会被唤醒并继续执行。因此,正确地传递Predicate参数就是在
cv.wait
函数中使用一个可调用对象(通常是lambda表达式或者函数对象),用于检查条件是否满足。 -
notify_one
:通知一个等待的线程。void notify_one();
这个函数用于通知一个正在等待的线程,使其从等待状态中唤醒。
-
notify_all
:通知所有等待的线程。void notify_all();
这个函数用于通知所有正在等待的线程,使它们从等待状态中唤醒。
这些成员函数可以与std::mutex
一起使用,用于在一个或多个线程中阻塞,直到另一个线程修改了共享变量并通知了condition_variable
。wait
函数会释放互斥锁,并在收到通知后重新获取互斥锁,从而实现线程的同步和通信。这些成员函数提供了一种有效的方式来协调多个线程的操作,以实现线程间的同步和通信。
实现线程间的通信
当使用std::condition_variable
时,通常会结合使用std::mutex
来实现线程间的通信。下面是一个实际的例子,演示了如何使用std::condition_variable
来实现生产者-消费者模式,实现线程间的同步和通信。
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> data_queue;
void producer() {
for (int i = 0; i < 10; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
{
std::lock_guard<std::mutex> lk(mtx);
data_queue.push(i);
std::cout << "Produced: " << i << std::endl;
}
cv.notify_one();
}
}
void consumer() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lk(mtx);
cv.wait(lk, [] { return !data_queue.empty(); });
int data = data_queue.front();
data_queue.pop();
std::cout << "Consumed: " << data << std::endl;
}
}
int main() {
std::thread producer_thread(producer);
std::thread consumer_thread(consumer);
producer_thread.join();
consumer_thread.join();
return 0;
}
在这个例子中,producer
线程向data_queue
中推送数据,而consumer
线程从data_queue
中取出数据。std::condition_variable
用于在consumer
线程中等待,直到data_queue
中有数据。这个例子展示了如何使用std::condition_variable
来实现线程间的通信,以及如何在多线程环境中实现同步。