生产者和消费者模型实现(基于条件变量)

基于条件变量的生产者和消费者模型实现

我们在这里使用使用一个生产者和一个消费者来实现。
并且使用一个定容的队列来作为两者的缓冲区域,即交易场所。
生产者与消费者模型及条件变量理解点这里

基本思路:
  • 生产者向队列中放入数据
  • 消费者从队列中拿走数据
  • 存放数据的队列最为两者共享区域,必须进行互斥访问,使用互斥量
  • 保持同步,避免饥饿问题。使用条件变量
  • 当队列为空时,消费者进行等待,直到被生产者唤醒
  • 消费者被唤醒后,拿走数据,并唤醒消费者
  • 当队列为满时,生产者进行等待,直到被消费者唤醒
  • 生产者被唤醒后,开始放入数据,并唤醒消费者

以上操作,使用互斥和同步,保证了两者有序且互不干扰的进行,保证了数据的安全和准确性。

以下是实现源码:

.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;
 }

以上便简单的实现了一个基于条件变量下的生产者与消费者模型。

猜你喜欢

转载自blog.csdn.net/M_jianjianjiao/article/details/84559745