生产者与消费者模型(C++)---互斥锁与条件变量共同实现

生产者与消费者模型

总的概括一下:一个场所,两种角色,三种关系,上图。
生产者与消费者模型(C++)---互斥锁与条件变量共同实现_第1张图片

  1. 一个场所:生产消费队列
  2. 两种角色:生产者与消费者
  3. 三种关系:生产者<—>生产者 消费者<—>消费者 生产者<—> 消费者

生产消费队列的安全性

条件变量和互斥锁有什么用:我们所用的STL提供的容器queue,并没有保证队列的安全性,所谓安全性,也就是三种关系之间的同步与互斥,因此我们需要用条件变量和互斥锁保证生产–消费队列是一个安全队列。

  • 同步:就生产者与消费者之间可以理解为,生产者生产完了消费者才能消费,产品生产到一半就被买走了是不合理的,可以理解为生产者与消费者之间的操作合理性。
  • 互斥:同样,互斥可以理解为生产者与生产者之间,消费者与消费者之间操作的合理性,生产者1生产时生产者2要等待,而不是与生产者1一同生产;消费者之间也类似,消费者1如果与消费者2同时消费,必定有一位消费者是没有真正的买到商品的,也就是花了钱却没买到东西。

实现

#define MAX_QUEUE 10
class BlockQueue{
  public:
    BlockQueue(int cap = MAX_QUEUE):_capacity(cap){
      pthread_mutex_init(&_mutex, NULL);
      pthread_cond_init(&_cond_con, NULL);
      pthread_cond_init(&_cond_pro, NULL);
    }
    ~BlockQueue(){
      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond_con);
      pthread_cond_destroy(&_cond_pro);
    }
    //入队
    void QueuePush(int data){
      QueueLock();
      while(QueueIsFull()){
        ProWait();
      }
      _queue.push(data);
      ConWakeUp();
      QueueUnlock();
    }
    //出队
    void QueuePop(int *data){
      QueueLock();
      while(QueueIsEmpty()){
        ConWait();
      }
      *data = _queue.front();
      _queue.pop();
      ProWakeUp();
      QueueUnlock();
    }
  private:
    void QueueLock(){
      pthread_mutex_lock(&_mutex);
    }//加锁
    void QueueUnlock(){
      pthread_mutex_unlock(&_mutex);
    }//解锁
    void ConWakeUp(){
      pthread_cond_signal(&_cond_con);
    }//唤醒消费者
    void ConWait(){
      pthread_cond_wait(&_cond_con, &_mutex);
    }//消费者等待
    void ProWait(){
      pthread_cond_wait(&_cond_pro, &_mutex);
    }//生产者等待
    void ProWakeUp(){
      pthread_cond_signal(&_cond_pro);
    }//唤醒生产者
    bool QueueIsFull(){
      return (_capacity == _queue.size());
    }//判断队列是否满了
    bool QueueIsEmpty(){
      return (0 == _queue.size());
    }//判断队列是否为空
  private:
    std::queue<int> _queue;
    int _capacity; //队列节点最大值
    //线程安全实现成员
    pthread_mutex_t _mutex;
    pthread_cond_t _cond_pro;
    pthread_cond_t _cond_con;
};

//消费者线程
void* thr_consumer(void* arg){
  BlockQueue *q = (BlockQueue*)arg;
  while(1){
    int data;
    q->QueuePop(&data);
    cout<<"consumer get data:" << data << endl;
  }
  return NULL;
}

int i = 0;//这里i创建为全局变量,是为了让每个生产者生产完都打印不一样的数字
pthread_mutex_t mutex;//i++不是原子操作,这里的锁是为了保证生产者之间的互斥,也就是
//生产者1生产时其他生产者不能生产,而消费者线程中没有非原子操作,因此消费者与消费者之前本身就是互斥的

//生产者线程
void* thr_productor(void* arg){
  BlockQueue *q = (BlockQueue*)arg;
  while(1){
    pthread_mutex_lock(&mutex);
    q->QueuePush(i++);
    cout<< "productor put data:" << i << endl;
    pthread_mutex_unlock(&mutex); 
  }
  return NULL;
}


int main(){
  BlockQueue q;
  pthread_t ctid[4], ptid[4];
  int i, ret;
  pthread_mutex_init(&mutex, NULL);//初始化锁
  //创建四个消费者
  for(i = 0; i < 4; i++){
    ret = pthread_create(&ctid[i], NULL, thr_consumer, (void*)&q);
    if(ret != 0){
      cout<<"pthread create error"<<endl;
      return -1;
    }
  }
  
  //创建四个消费者
  for(i = 0; i < 4; i++){
    ret = pthread_create(&ptid[i], NULL, thr_productor, (void*)&q);
    if(ret != 0){
      cout<<"pthread create error"<<endl;
      return -1;
    }
 }
    
 for(i = 0; i < 4; i++){
   pthread_join(ctid[i], NULL);
	}
 for(i = 0; i < 4; i++){
   pthread_join(ptid[i], NULL);
	}
	
}

你可能感兴趣的:(C++)