[Linux]生产者消费者模型----条件变量

概述

生产者消费者模型:一种典型的设计模式,是人们根据典型场景设计的解决方案

应用场景:应用于有大量的数据产生和进行处理的场景

具体实现:具有多个生产者和消费者线程来生产和处理庞大的数据量,但是生产者和消费者并不直接交互,而是通过中间的缓冲区进行协调工作;生产者产生数据存入缓冲区,消费者从缓冲区中拿到数据后进行处理。

在这里插入图片描述

优点:
解耦合:分离生产和消费,当数据的处理方式发生改变时,仅仅改变消费者即可
支持忙闲不均:如果生产的数据量过大,可以先存放在缓冲区中,让消费者慢慢处理
支持并发:可以开多个生产者线程或者消费者线程进行工作

为了能够支持并发,必须保证线程安全:
1、每个生产者之间应该保持互斥关系;每个消费者之间也应该保持互斥关系;
2、生产者与消费者之间应该保持同步与互斥关系

实现

底层实现:生产者线程和消费者线程(一个入队,一个出队) + 保证线程安全的队列作为缓冲区

1、实现线程安全队列
封装一个线程安全的队列类:class BlockQueue—阻塞队列
有空闲结点可以数据入队,没有则阻塞入队线程;
有数据结点可以数据出队,没有则阻塞出队线程;

思路:

class BlockQueue{
private:
 	int capacity;				//容量
 	std::queue<int> _queue;		//底层封装一个队列
 	pthread_mutex_t mutex;		//互斥锁
 	pthread_cond_t cond_pro;	//生产者条件变量
 	pthread_cond_t cond_cus;	//消费者条件变量
public:
 	BlockQueue(int capacity=5);	//构造函数
 	bool push(int data);		//入队
 	bool pop(int* data);		//出队
 	~BlockQueue();				//析构
};

2、创建线程进行数据入队、出队

完整代码:

#include<iostream>
#include<queue>
#include<pthread.h>
#include<cstdio>
#include<unistd.h>


class BlockQueue{
  private:
    int capacity;               //容量
    std::queue<int> _queue;     //底层封装一个队列
    pthread_mutex_t mutex;      //互斥锁
    pthread_cond_t cond_pro;    //生产者条件变量
    pthread_cond_t cond_cus;    //消费者条件变量
public:

    BlockQueue(int cap=5):capacity(cap){
      pthread_mutex_init(&mutex,NULL);
      pthread_cond_init(&cond_pro,NULL);
      pthread_cond_init(&cond_cus,NULL);

    }

    bool Push(int data){
     pthread_mutex_lock(&mutex);
     while(_queue.size()==capacity){
       pthread_cond_wait(&cond_pro,&mutex);
     }
     _queue.push(data);
     pthread_cond_signal(&cond_cus);
     pthread_mutex_unlock(&mutex);
      return true;
    }

    bool Pop(int* data){
      pthread_mutex_lock(&mutex);
      while(_queue.empty()){
        pthread_cond_wait(&cond_cus,&mutex);
      }
      *data=_queue.front();
      _queue.pop();
      pthread_cond_signal(&cond_pro);
      pthread_mutex_unlock(&mutex);
      return true;
    } 

    ~BlockQueue(){

      pthread_mutex_destroy(&mutex);
      pthread_cond_destroy(&cond_pro);
      pthread_cond_destroy(&cond_cus);
    }              
};

void* productor(void* arg){
  BlockQueue* q=(BlockQueue*)arg;
  int i=0;
  while(1){
    q->Push(i);
    printf("生产者入队数据:%d\n",i++);
  }
  return NULL;
}
void* customer(void* arg){
  BlockQueue* q=(BlockQueue*)arg;
  while(1){
    int data;
    q->Pop(&data);
    printf("消费者出队数据:%d\n",data);
  }
  return NULL;
}

int main(){
  BlockQueue q;
  pthread_t ptid[4],ctid[4];
  int ret;
  for(int i=0;i<4;i++){
    ret=pthread_create(&ptid[i],NULL,productor,&q);
    if(ret!=0){
      printf("create thread error\n");
      return -1;
    }
  } 

  for(int i=0;i<4;i++){
    ret=pthread_create(&ctid[i],NULL,customer,&q);
    if(ret!=0){
      printf("create thread error\n");
      return -1;
    }
  }

  for(int i=0;i<4;i++){
    pthread_join(ptid[i],NULL);
    pthread_join(ctid[i],NULL);
  }
  return 0;
}


部分结果:
在这里插入图片描述

注意:
这里我们定义的容量是5,所以正常情况下应该是入队5次,出队5次交替进行,但是由于cus和pro线程中的操作是非原子操作,所以时间片轮转时可能会打断之前未完成的操作。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中,可以使用C语言的条件变量和线程来实现消费者-生产者模型。下面是一个简单的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define BUFFER_SIZE 10 int buffer[BUFFER_SIZE]; int count = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond_prod = PTHREAD_COND_INITIALIZER; pthread_cond_t cond_cons = PTHREAD_COND_INITIALIZER; void *producer(void *arg) { int item = 0; while (1) { pthread_mutex_lock(&mutex); // 如果缓冲区已满,则等待消费者消费 while (count == BUFFER_SIZE) { pthread_cond_wait(&cond_prod, &mutex); } buffer[count] = item; count++; printf("Producer produced item %d\n", item); // 唤醒消费者线程 pthread_cond_signal(&cond_cons); pthread_mutex_unlock(&mutex); item++; } pthread_exit(NULL); } void *consumer(void *arg) { while (1) { pthread_mutex_lock(&mutex); // 如果缓冲区为空,则等待生产者生产 while (count == 0) { pthread_cond_wait(&cond_cons, &mutex); } int item = buffer[count - 1]; count--; printf("Consumer consumed item %d\n", item); // 唤醒生产者线程 pthread_cond_signal(&cond_prod); pthread_mutex_unlock(&mutex); } pthread_exit(NULL); } int main() { pthread_t producer_thread, consumer_thread; // 创建生产者和消费者线程 pthread_create(&producer_thread, NULL, producer, NULL); pthread_create(&consumer_thread, NULL, consumer, NULL); // 等待线程结束 pthread_join(producer_thread, NULL); pthread_join(consumer_thread, NULL); return 0; } ``` 在上面的代码中,生产者线程不断地向缓冲区中生产数据,而消费者线程不断地从缓冲区中消费数据。当缓冲区满时,生产者线程会等待条件变量`cond_prod`,直到有消费者消费数据才会被唤醒。同样,当缓冲区为空时,消费者线程会等待条件变量`cond_cons`,直到有生产者生产数据才会被唤醒。 需要注意的是,在生产者和消费者线程之间共享的变量`count`和`buffer`需要进行互斥访问,因此使用了互斥锁`mutex`来保护共享资源的访问。 希望这个示例能帮助你理解如何在Linux中使用C语言的条件变量和线程实现消费者-生产者模型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值