std::condition_variable
是 C++ 标准库 <condition_variable>
头文件中提供的一个用于线程间同步的工具,它允许线程在某个条件满足时被唤醒。通常与 std::mutex
或 std::unique_lock
配合使用,在多线程编程中非常有用,比如实现生产者 - 消费者模型等场景。下面将从基本概念、工作原理、常用方法、应用场景和示例代码等方面详细介绍 std::condition_variable
。
基本概念
std::condition_variable
本质上是一个同步原语,它提供了一种机制,让线程可以阻塞自己,直到另一个线程通知它某个条件已经满足。当一个线程等待条件变量时,它会释放持有的互斥锁,进入阻塞状态;当其他线程通知条件变量时,等待的线程会被唤醒,并尝试重新获取互斥锁。
工作原理
- 等待操作:当一个线程调用
std::condition_variable
的wait
方法时,它会自动释放当前持有的互斥锁,并进入阻塞状态。此时,其他线程可以获取该互斥锁并修改共享状态。 - 通知操作:当另一个线程修改了共享状态,并且满足了某个条件时,它可以调用
std::condition_variable
的notify_one
或notify_all
方法。notify_one
会唤醒一个等待在该条件变量上的线程,而notify_all
会唤醒所有等待在该条件变量上的线程。 - 重新锁定:被唤醒的线程会尝试重新获取之前释放的互斥锁,一旦获取成功,它会继续执行后续的代码。
常用方法
wait
系列方法:void wait( std::unique_lock<std::mutex>& lock );
:阻塞当前线程,直到收到通知。调用该方法时,线程会自动释放lock
持有的互斥锁,并进入等待状态;当收到通知并重新获取互斥锁后,线程会继续执行。template< class Predicate > void wait( std::unique_lock<std::mutex>& lock, Predicate pred );
:阻塞当前线程,直到收到通知且pred
条件为true
。该方法会在每次被唤醒时检查pred
的返回值,如果为false
则继续等待。
notify
系列方法:void notify_one();
:唤醒一个等待在该条件变量上的线程。如果没有线程在等待,则该调用没有效果。void notify_all();
:唤醒所有等待在该条件变量上的线程。
应用场景
- 生产者 - 消费者模型:生产者线程生产数据并放入缓冲区,消费者线程从缓冲区取出数据进行处理。当缓冲区为空时,消费者线程可以等待条件变量;当生产者线程放入数据后,通知消费者线程。
- 多线程任务同步:在某些场景下,一个线程需要等待其他线程完成特定任务后才能继续执行,此时可以使用条件变量进行同步。
示例代码(生产者 - 消费者模型)
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
std::queue<int> buffer;
std::mutex mtx;
std::condition_variable notFull;
std::condition_variable notEmpty;
const int MAX_SIZE = 5;
// 生产者线程函数
void producer() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
// 等待缓冲区不满
notFull.wait(lock, [] { return buffer.size() < MAX_SIZE; });
buffer.push(i);
std::cout << "Produced: " << i << std::endl;
// 通知消费者缓冲区非空
notEmpty.notify_one();
}
}
// 消费者线程函数
void consumer() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
// 等待缓冲区非空
notEmpty.wait(lock, [] { return!buffer.empty(); });
int value = buffer.front();
buffer.pop();
std::cout << "Consumed: " << value << std::endl;
// 通知生产者缓冲区不满
notFull.notify_one();
}
}
int main() {
std::thread producerThread(producer);
std::thread consumerThread(consumer);
producerThread.join();
consumerThread.join();
return 0;
}
通过使用 std::condition_variable
,实现了生产者和消费者线程之间的同步,确保了在缓冲区满时生产者线程等待,在缓冲区空时消费者线程等待。