一个场所,两种角色,三种关系
一个场所是指缓冲区
两种角色是指生产者和消费者
三种关系是指:
生产者与生产者的互斥关系
消费者与消费者的互斥关系
生产者与消费者的同步+互斥关系
生产者与消费者模型的优点:
1.解耦合:即不需要直接进行数据交互
2.支持并发:即多个线程可以同时操作场所
3.支持忙闲不均
三个优点都是通过这个场所来提供,但是因为多个角色有可能同时操作场所,所以要保证场所的操作安全
用阻塞队列+条件变量来模拟实现生产者消费者模型
#include
#include
#include
#define MAX_QUEUE 10
class BlockQueue
{
private:
std::queue _queue;
int _capacity;//queue是动态增长的,需要限制队列中最大节点数量
pthread_mutex_t _mutex;
pthread_cond_t _cond_product;
pthread_cond_t _cond_consumer;
public:
//初始化
BlockQueue(int cap = MAX_QUEUE):_capacity(cap) {
pthread_mutex_init(&_mutex, NULL);
pthread_cond_init(&_cond_product, NULL);
pthread_cond_init(&_cond_consumer, NULL);
}
~BlockQueue() {
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond_product);
pthread_cond_destroy(&_cond_consumer);
}
//生产者入队列
bool QueuePush(int data) {
pthread_mutex_lock(&_mutex);
while(_queue.size() == _capacity)
//队列满,生产者等待
{
pthread_cond_wait(&_cond_product, &_mutex);
}
_queue.push(data);
pthread_cond_signal(&_cond_consumer);
pthread_mutex_unlock(&_mutex);
}
//消费者出队列
bool QueuePop(int &data) {
pthread_mutex_lock(&_mutex);
while(_queue.empty())
//队列空,消费者等待
{
pthread_cond_wait(&_cond_consumer, &_mutex);
}
data = _queue.front();//获取队首节点
_queue.pop();
pthread_cond_signal(&_cond_product);
pthread_mutex_unlock(&_mutex);
}
};
//生产者入口函数
void *thr_product (void *arg)
{
BlockQueue *q = (BlockQueue*)arg;
int i = 0;
while(1) {
q->QueuePush(i++);//将数据放入
std::cout<<"productor:"<QueuePop(data);//将数据取出
std::cout<<"consumer:"<
用环形队列+信号量来模拟实现生产者消费者模型
需要先实现一个环形队列,再用信号量实现互斥锁
class RingQueue
{
private:
std:vector_queue;
int _capacity;
int _read; //读
int _write; //写
sem_t lock;
sem_t _idle_space; //空闲空间大小,初始化为capacity,生产者在这个队列等待
sem_t _data_space; //队列中的数据个数,初始化为0,消费者在这个队列等待
public:
QueuePush(int data); //入队列
QueuePop(int &data); //出队列
}
#include
#include
#include
#include
#define MAX_QUEUE 10
class RingQueue
{
private:
std::vector _queue;
int _capacity;
int _read;
int _write;
sem_t _lock;
//生产者入队数据之前判断队列中是否有空闲空间;判断能否入队数据
sem_t _idle_space;
//消费者获取数据之前判断有数据的空间有多少判断能否获取数据
sem_t _data_space;
public:
RingQueue(int maxque = MAX_QUEUE):_capacity(maxque), _queue(maxque)
{
sem_init(&_lock, 0, 1);
sem_init(&_idle_space, 0, _capacity);
sem_init(&_data_space, 0, 0);
}
~RingQueue(){
sem_destroy(&_lock);
sem_destroy(&_idle_space);
sem_destroy(&_data_space);
}
bool QueuePush(int data) {
sem_wait(&_idle_space);//判断是否有资源可以操作
sem_wait(&_lock);//下方属于临界资源,需要被保护
_queue[_write] = data;
_write = (_write + 1) % _capacity;
sem_post(&_lock);
sem_post(&_data_space);//数据空间计数+1;唤醒消费者取数据
return true;
}
bool QueuePop(int &data) {
sem_wait(&_data_space);//通过数据空间计数判断是否有数据操作
sem_wait(&_lock);
data = _queue[_read];
_read = (_read + 1) % _capacity;
sem_post(&_lock);
sem_post(&_idle_space);//空闲空间计数+1;唤醒生产者
return true;
}
};
//入队数据
void *productor(void *arg)
{
RingQueue *q = (RingQueue*)arg;
int i = 0;
while(1) {
std::cout << "productor put a data: " << i<QueuePush(i++);
}
return NULL;
}
//出队数据
void *consumer(void *arg)
{
RingQueue *q = (RingQueue*)arg;
while(1) {
int data;
q->QueuePop(data);
std::cout << "consumer get a data: "<< data << std::endl;
}
return NULL;
}
int main()
{
pthread_t p_tid[4], c_tid[4];//创建四个生产者和四个消费者线程
RingQueue q;
for (int i = 0; i < 4; i++) {
int ret = pthread_create(&p_tid[i], NULL, productor, (void*)&q);
if (ret != 0) {
std::cout << "pthread productor create error\n";
return -1;
}
}
for (int i = 0; i < 4; i++) {
int ret = pthread_create(&c_tid[i], NULL, consumer, (void*)&q);
if (ret != 0) {
std::cout << "pthread consumer create error\n";
return -1;
}
}
for(int i = 0; i < 4; i++) {
pthread_join(c_tid[i], NULL);
}
for(int i = 0; i < 4; i++) {
pthread_join(p_tid[i], NULL);
}
return 0;
}