基于条件变量的生产者和消费者模型实现
我们在这里使用使用一个生产者和一个消费者来实现。
并且使用一个定容的队列来作为两者的缓冲区域,即交易场所。
生产者与消费者模型及条件变量理解点这里
基本思路:
- 生产者向队列中放入数据
- 消费者从队列中拿走数据
- 存放数据的队列最为两者共享区域,必须进行互斥访问,使用互斥量
- 保持同步,避免饥饿问题。使用条件变量
- 当队列为空时,消费者进行等待,直到被生产者唤醒
- 消费者被唤醒后,拿走数据,并唤醒消费者
- 当队列为满时,生产者进行等待,直到被消费者唤醒
- 生产者被唤醒后,开始放入数据,并唤醒消费者
以上操作,使用互斥和同步,保证了两者有序且互不干扰的进行,保证了数据的安全和准确性。
以下是实现源码:
.hpp 文件
#ifndef __BLOCKQUEUE_HPP__
#define __BLOCKQUEUE_HPP__
#include <iostream>
#include <pthread.h>
#include <queue>
#include <stdlib.h>
#include <time.h>
//为生产者与消费者创建一个交易场所
template<class T>
class BlockQueue{
public:
BlockQueue(const int& cap)
:_cap(cap)
{
pthread_mutex_init(&lock,NULL); // pthread_cond_init(&cond_c,NULL);
pthread_cond_init(&cond_p,NULL);
}
void Push_Data(const T& value) //放入数据
{
LockQueue();
while(IsFull()) //判断队列是否为满,函数调用可能失败,使用while进行轮询式检测
ProductWait();
SignalConsume();
bq.push(value); //不满插入数据
UnLockQueue();
}
void Pop_Data(T& data) //取出,并从队列中删除数据
{
LockQueue();
while(IsEmpty()) //判断是否为空
ConsumeWait();
SignalProduct();
data=bq.front(); //取出数据
bq.pop();
UnLockQueue();
}
~BlockQueue()
{
pthread_mutex_destroy(&lock); //销毁条件变量与互斥锁
pthread_cond_destroy(&cond_c);
pthread_cond_destroy(&cond_p);
}
private:
//将对互斥锁和条件变量的操作私有化防止被从类外访问
void LockQueue() //上锁
{
pthread_mutex_lock(&lock);
}
void UnLockQueue() //解锁
{
pthread_mutex_unlock(&lock);
}
void ConsumeWait() //消费者等待
{
pthread_cond_wait(&cond_c,&lock);
}
void ProductWait() //生产者等待
{
pthread_cond_wait(&cond_p,&lock);
}
void SignalConsume() //通知消费者
{
pthread_cond_signal(&cond_c);
}
void SignalProduct() //通知生产者
{
pthread_cond_signal(&cond_p);
}
bool IsEmpty() //队列是否为空
{
return bq.size() == 0;
}
bool IsFull() //队列是否已满
{
return bq.size() == _cap;
}
private:
std::queue<T> bq; //为生产者与消费者建立一个存放数据的队列
int _cap; //限定了该队列的大小为cap
pthread_mutex_t lock; //互斥锁用于保护临界区
pthread_cond_t cond_c; //两个条件变量分别对应 队列为空时的
pthread_cond_t cond_p; //对应队列为满时
};
#endif
.cc 文件
#include "blockqueue.hpp"
const int QUEUE_CAP = 5;
void* consume_routine(void* arg)
{
BlockQueue<int>* p = (BlockQueue<int>*) arg;
srand((unsigned long)time(NULL));
int data;
while(1)
{
data = rand() % 100 +1;
p->Push_Data(data);
std::cout<<"product push the data: "<<data<<std::endl;
}
}
void* product_routine(void* arg)
{
BlockQueue<int>* p = (BlockQueue<int>*) arg;
int data;
while(1)
{
p->Pop_Data(data);
std::cout<<"consume get the data : "<<data<<std::endl;
}
}
int main()
{
pthread_t consume;
pthread_t product;
BlockQueue<int>* p = new BlockQueue<int>(QUEUE_CAP); //创建一个存放数据的区域
pthread_create(&consume,NULL,consume_routine,(void*)p);
pthread_create(&product,NULL,product_routine,(void*)p);
pthread_join(consume,NULL);
pthread_join(product,NULL);
delete p;
return 0;
}
以上便简单的实现了一个基于条件变量下的生产者与消费者模型。