生产者消费者模式
o.引言
假设有两个进程(或线程)A、B和一个固定大小的缓冲区,A进程生产数据放入缓冲区,B进程从缓冲区中取出数据进行计算,这就是一个简单的生产者-消费者模型。这里的A进程相当于生产者,B进程相当于消费者。

生产者/消费者模式是一种常见的并发编程模式,其中生产者线程生成数据并将其放入缓冲区,而消费者线程从缓冲区中取出数据进行处理。这种模式通过缓冲区解耦了生产者和消费者的速度差异。
生产者-消费者模型特点
- 保证生产者不会在缓冲区满的时候继续向缓冲区放入数据,而消费者也不会在缓冲区空的时候,消耗数据
- 当缓冲区满的时候,生产者会进入休眠状态,当下次消费者开始消耗缓冲区数据时,生产者才会被唤醒,开始往缓冲区中添加数据;当缓冲区空的时候,消费者也会进入休眠状态,知道生产者往缓冲区添加数据时才会被唤醒
生产者-消费者模型的优点
- (1)解耦合:将生产者类和消费者类进行解耦,消除代码之间的依赖性,简化工作负载的管理
- (2)复用:通过生产者和消费者类独立开来,那么可以对生产者类型和消费者类进行独立的复用和扩展
- (3)调整并发数:由于生产者和消费者的处理速度是不一样的,可以调整并发数,给予慢的一方多的并发数,来提高任务的处理速度
- (4)异步:对于生产者和消费者来说能各司其职,生产者只需要关心缓冲区是否还有数据,不需要等待消费者处理完;同样对于消费者涞水,也只需要关注缓冲区的内容,不需要关注生产者,通过异步的方式支持高并发,将一个耗时的流程拆成生产和消费两个阶段,这样生产者因为执行put()的时间比较短,而支持高并发。
- (5)支持分布式:生产者和消费者通过队列进行通信,所有不需要在同一台机器上,在分布式环境中可以通过redis的list作为队列,而消费者只需要轮询队列中是否有数据。同事还能支持集群的伸缩性,当某台机器宕掉的时候不会导致整个集群宕掉。


1.demo
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <chrono>
// 共享队列和相关同步机制
std::queue<int> buffer;
const unsigned int buffer_size = 10;
std::mutex mtx;
std::condition_variable cv_producer, cv_consumer;
// 生产者函数
void producer(int id, int produce_count) {
for (int i = 0; i < produce_count; ++i) {
std::unique_lock<std::mutex> lock(mtx);
cv_producer.wait(lock, [] {
return buffer.size() < buffer_size; });
buffer.push(i);
std::cout << "Producer " << id << " produced: " << i << std::endl;
lock.unlock();
cv_consumer.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟生产延迟
}
}
// 消费者函数
void consumer(int id, int consume_count) {
for (int i = 0; i < consume_count; ++i) {
std::unique_lock<std::mutex> lock(mtx);
cv_consumer.wait(lock, [] {
return !buffer.empty(); });
int item = buffer.front();
buffer