C++条件变量实战:生产者消费者模型
·
好的,我们来详细探讨 C++ 中 std::condition_variable 的使用方法。条件变量是多线程同步的强大工具,常用于线程间的等待与通知机制,特别是在 生产者-消费者模型 或需要等待特定条件满足的场景中。
核心概念
std::condition_variable
用于阻塞一个或多个线程,直到另一线程修改共享变量并通知条件变量。std::mutex
条件变量必须与互斥锁配合使用,确保对共享数据的操作是线程安全的。wait()
线程调用wait()后会释放锁并阻塞,直到被其他线程唤醒。唤醒后会自动重新获取锁。notify_one()/notify_all()
唤醒一个或所有等待中的线程。
实战示例:生产者-消费者模型
以下是一个简单的生产者-消费者示例,使用条件变量协调生产和消费操作。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> data_queue; // 共享数据缓冲区
const int MAX_SIZE = 10; // 缓冲区最大容量
// 生产者线程
void producer() {
for (int i = 0; i < 20; ++i) {
std::unique_lock<std::mutex> lock(mtx);
// 等待缓冲区非满
cv.wait(lock, []{ return data_queue.size() < MAX_SIZE; });
data_queue.push(i);
std::cout << "Produced: " << i << std::endl;
lock.unlock();
// 通知一个消费者
cv.notify_one();
}
}
// 消费者线程
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
// 等待缓冲区非空
cv.wait(lock, []{ return !data_queue.empty(); });
int data = data_queue.front();
data_queue.pop();
std::cout << "Consumed: " << data << std::endl;
lock.unlock();
// 通知一个生产者
cv.notify_one();
}
}
int main() {
std::thread p1(producer);
std::thread c1(consumer);
p1.join();
c1.join();
return 0;
}
关键点解析
-
wait()的谓词参数cv.wait(lock, []{ return !data_queue.empty(); });- 避免 虚假唤醒(Spurious Wakeup),确保条件真正满足后才继续执行。
- 相当于:
while (!condition) { cv.wait(lock); }
-
锁的作用域
- 使用
std::unique_lock灵活管理锁的生命周期。 - 在
wait()前加锁,wait()内部会自动释放锁;被唤醒后重新获取锁。
- 使用
-
通知机制
notify_one():唤醒一个等待线程(效率高)。notify_all():唤醒所有等待线程(适用于多个消费者/生产者)。
使用场景建议
- 任务队列:线程池中的任务调度。
- 事件驱动:等待外部事件(如网络数据到达)。
- 资源限制:控制并发访问资源的最大数量。
注意事项
- 死锁风险
确保所有分支路径都能正确释放锁或通知条件变量。 - 生命周期管理
确保条件变量和互斥锁的存活时间覆盖所有线程的操作。
通过合理使用条件变量,可以高效实现复杂的线程协作逻辑。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)