-
什么是生产者与消费者模型
一个场所, 两种角色, 三种关系- 两种角色: 生产者与消费者
- 三种关系:
1.同步关系
2.互斥关系
3.同步加互斥关系
-
为什么使用这种模型
1.解耦合
2.支持忙闲不均
3.支持并发 -
实现
1.基于信号量来实现生产者与消费者模型
/*
* 文件名称:
* * 创 建
* * 创建日期:
* * 描 述:使用信号量实现生产者与消费者模型 , 唤醒队列
* ================================================================*/
#include <iostream>
#include <vector>
#include <thread>
#include <semaphore.h>
#define MAXQ 10
class RingQueue
{
public:
RingQueue(int maxq = MAXQ)
:_queue(maxq)
,_capacity(maxq)
{
sem_init(&_lock , 0 , 1);//第二个参数0/1表示用于线程间或进程间,0为线程
sem_init(&_idle_space , 0 , maxq);
sem_init(&_data_space, 0 , 0);
}
~RingQueue()
{
sem_destroy(&_lock);
sem_destroy(&_data_space);
sem_destroy(&_idle_space);
}
bool QueuePush(int data)
{
sem_wait(&_idle_space);//判断队列是否满了
sem_wait(&_lock);//计数-1 加锁
_queue[_step_write] = data;
_step_write = (_step_write + 1) % _capacity;//写指针向后移动
sem_post(&_lock);//进行计数+1 解锁
sem_post(&_data_space);//数据空间+1
return true;
}
bool QueuePop(int &data)
{
sem_wait(&_lock);
sem_wait(&_data_space);
data = _queue[_step_read];
_step_read = (_step_read + 1) % _capacity;
sem_post(&_lock);
sem_post(&_idle_space);//空闲空间多一个 唤醒生产者
return true;
}
private:
std::vector<int> _queue;
int _capacity;//节点限制
int _step_read;//读指针
int _step_write;//写指针
sem_t _lock;
sem_t _idle_space;//空闲空间计数
sem_t _data_space;//数据空间计数
};
void thr_producer(RingQueue *q)
{
int data = 0;
while(1)
{
q->QueuePush(data);
std::cout << "put data------" << data++ << std::endl;
}
return;
}
void thr_consumer(RingQueue *q)
{
int data = 0 ;
while(1)
{
q->QueuePop(data);
std::cout << "get data--"<< data << std::endl;
}
return;
}
int main()
{
RingQueue q;
std::vector<std::thread> list_con(4);
std::vector<std::thread> list_pro(4);
for(int i = 0 ; i < 4 ; i++)
{
list_pro[i] = std::thread (thr_producer , &q ,std::ref(q));
}
for(int i = 0 ; i < 4 ; i++)
{
list_con[i] = std::thread(thr_consumer , &q);
}
for(int i = 0 ; i < 4 ; i++)
{
list_con[i].join();
list_pro[i].join();
}
return 0 ;
}
2.基于互斥锁与条件变量实现生产者与消费者模型
/*===============================================================
* Copyright (C) . All rights reserved.")
* 文件名称:
* 创 建 者:zhang
* 创建日期:
* 描 述:基于互斥锁与条件变量实现一个线程安全的队列
* 实现生产者与消费者模型
================================================================*/
#include <iostream>
#include <pthread.h>
#include <queue>
#define MAXQ 10
class BlockQueue{
private:
std::queue<int> _queue;
int _capacity;
pthread_mutex_t _mutex;
pthread_cond_t _cond_productor;
pthread_cond_t _cond_consumer;
public:
BlockQueue(int maxq = MAXQ)
:_capacity(maxq)
{
pthread_mutex_init(&_mutex , NULL);
pthread_cond_init(&_cond_productor , NULL);
pthread_cond_init(&_cond_consumer , NULL);
}
~BlockQueue()
{
pthread_mutex_destroy(&_mutex);
pthread_cond_destroy(&_cond_productor);
pthread_cond_destroy(&_cond_consumer);
}
// bool IsFull()
// {
// return (_queue.size() == _capacity ? true : false);
// }
bool QueuePush(int data)
{
pthread_mutex_lock(&_mutex);
while(_queue.size() == _capacity)
{
pthread_cond_wait(&_cond_productor , &_mutex);
}
_queue.push(data);
pthread_mutex_unlock(&_mutex);
pthread_cond_signal(&_cond_consumer);
return true;
}
bool QueuePop(int &data)
{
pthread_mutex_lock(&_mutex);
while(_queue.empty())
{
pthread_cond_wait(&_cond_consumer , &_mutex);
}
data = _queue.front();
_queue.pop();
pthread_mutex_unlock(&_mutex);
pthread_cond_signal(&_cond_productor);
return true;
}
};
void *thr_consumer(void *arg)
{
BlockQueue *q = (BlockQueue*)arg;
int data;
while(1)
{
q->QueuePop(data);
std::cout << "consumer get a piece of data --"<< data << "\n";
}
}
void *thr_productor(void *arg)
{
BlockQueue *q = (BlockQueue*)arg;
int data = 0;
while(1)
{
q->QueuePush(data);
std::cout << "productor produces a data" << data ++ << "\n";
}
return NULL;
}
#define MAXTHR 1
int main()
{
pthread_t ctid[MAXTHR] , ptid[MAXTHR];
int ret , i;
BlockQueue q;
for(i = 0 ; i <MAXTHR ; i++)
{
ret = pthread_create( &ctid[i] , NULL , thr_consumer , (void*)&q);
if(ret != 0 )
{
std::cout << "creadte thread error \n";
return -1;
}
}
for(i = 0 ; i < MAXTHR ; i++)
{
ret = pthread_create(&ptid[i] , NULL , thr_productor , (void*)&q);
if(ret != 0)
{
std::cout << "creat thread error \n";
return -1;
}
}
for(i = 0 ;i < MAXTHR ; i++)
{
pthread_join(ctid[i] , NULL);
pthread_join(ptid[i] , NULL);
}
return 0;
}