文章目录
Linux线程
6. 生产消费者模型
生产消费者模型的概念
生产者消费者模型 是一种常见的并发编程模型。
在这个模型中,通常存在两类角色:生产者和消费者。
生产者负责生成数据或产品,并将其放入一个共享的缓冲区中。而消费者则从缓冲区中取出数据或产品进行消费处理。
为何要使用生产者消费者模型
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。这个阻塞队列就是用来给生产者和消费者解耦的。
简单的说:就是为了解决生产者和消费者之间的速度不匹配问题。
生产者消费者模型优点
解耦、支持并发、支持忙闲不均。
上图中有"321"原则:
3种关系:生产者和生产者(互斥)、消费者和消费者(互斥)、生产者和消费者(互斥、同步)。
2种角色:生产者和消费者。
1个交易场所:特定结构的内存空间。
6.1 基于阻塞队列的生产消费者模型
基于阻塞队列的生产消费者模型的概念
基于阻塞队列的生产消费者模型 是一种用于协调生产者和消费者之间工作流程的编程模式。
实现的原理
在这个模型中,生产者负责生成数据或产品,并将其放入一个阻塞队列中。阻塞队列是一种特殊的数据结构,当队列已满时,生产者尝试添加新元素的操作会被阻塞,直到队列有足够的空间。
消费者则从这个阻塞队列中获取数据或产品进行处理。当队列为空时,消费者尝试获取元素的操作会被阻塞,直到生产者向队列中添加了新的元素。
6.1.1 阻塞队列模型实现
这是我们的任务对象,一个简单的模拟加减乘除计算:
#pragma once
#include <iostream>
#include <string>
std::string opers="+-*/%";
enum{
DivZero=1,
ModZero,
Unknown
};
class Task
{
public:
Task()
{
}
Task(int x,int y,char op)
:_data1(x),_data2(y),_oper(op),_result(0),_exitcode(0)
{
}
void run()
{
switch (_oper)
{
case '+':
_result=_data1+_data2;
break;
case '-':
_result=_data1-_data2;
break;
case '*':
_result=_data1*_data2;
break;
case '/':
{
if(_data2==0) _exitcode=DivZero;
else _result=_data1/_data2;
}
break;
case '%':
{
if(_data2==0) _exitcode=ModZero;
else _result=_data1%_data2;
}
break;
default:
_exitcode=Unknown;
break;
}
}
//Task对象重载运算符(),()直接进行run函数
void operator()()
{
run();
}
std::string GetResult()
{
std::string r=std::to_string(_data1);
r+=_oper;
r+=std::to_string(_data2);
r+="=";
r+=std::to_string(_result);
r+="[code: ";
r+=std::to_string(_exitcode);
r+="]";
return r;
}
std::string GetTask()
{
std::string r=std::to_string(_data1);
r+=_oper;
r+=std::to_string(_data2);
r+="=?";
return r;
}
~Task()
{
}
private:
int _data1;
int _data2;
char _oper;
int _result;
int _exitcode;
};
这是我们实现的阻塞队列模型:
#pragma once
#include <iostream>
#include <queue>
#include