生产者与消费者模型

简介: 生产者与消费者模型

一、生产者与消费者模型简介


生产者与消费者模型:是一种设计模式。


       设计模式:针对典型的应用场景设计的解决方案。


       应用场景:具有资源的产生与处理的场景。


优点:


       1)解耦合


       生产者与消费者通过缓冲区通信,不再是直接通信,降低耦合度。


       2)支持忙闲不均


       一定程度解决一方过闲,一方过忙的问题。


       3)支持并发(缓冲区必须线程安全)


       多线程处理。


二、生产者与消费者模型的实现


1.具有多个生产者&消费者线程


2.具备线程安全的缓冲区


       线程安全:


       生产者与生产者的关系:互斥


       生产者与消费者的关系:同步 + 互斥


       消费者与消费者的关系:互斥


实现关键:


       创建一个线程安全的缓冲区,然后创建生产者与消费者


3.线程安全的缓冲区(队列)的实现


3.1基于阻塞队列、互斥锁、条件变量的实现


template <class T>
class BlockQueue {
    private:
        int _capacity;
        std::queue<T> _queue;
        pthread_mutex_t _mutex;
        pthread_cond_t _cond_pro;
        pthread_cond_t _cond_con;
    public:
        BlockQueue();
        ~BlockQueue();
        bool Push(const T &data);
        bool Pop(T *data);
};


3.2基于环形队列、信号量的实现


template <class T>
class CircularQueue {
    pricate:
        //实现环形队列
        std::vector<T> _array;
        int _capacity;
        int _front = 0;
        int _rear = 0;
        //实现同步
        sem_t _sem_idle;//对队列空闲空间计数
        sem_t _sem_data;//对有效数据节点计数
        //实现互斥
        sem_t _sem_lock;//实现互斥锁
};


三、代码实现


1.基于阻塞队列、互斥锁,条件变量的实现


#include<iostream>
#include<cstdlib>
#include<unistd.h>
#include<pthread.h>
#include<queue>
#define MAX_QUEUE 5
#define PRODUCER 4
#define CONSUMER 4
template <class T>
class BlockQueue{
  private:
    int _capacity;//缓冲区容量
    std::queue<T> _queue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond_pro;
    pthread_cond_t _cond_con;
  public:
    BlockQueue(int cap = MAX_QUEUE) : _capacity(cap) {
      pthread_mutex_init(&_mutex, NULL);
      pthread_cond_init(&_cond_pro, NULL);
      pthread_cond_init(&_cond_con, NULL);
    }
    ~BlockQueue() {
      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond_pro);
      pthread_cond_destroy(&_cond_con);
    }
    bool Push(const T &data) {
      pthread_mutex_lock(&_mutex);
      while (_queue.size() == _capacity) {
        pthread_cond_wait(&_cond_pro, &_mutex);
      }
      _queue.push(data);
      pthread_cond_signal(&_cond_con);
      pthread_mutex_unlock(&_mutex);
    }
    bool Pop(T *data) {
      pthread_mutex_lock(&_mutex);
      while (_queue.empty()) {
        pthread_cond_wait(&_cond_con, &_mutex);
      }
      *data = _queue.front();
      _queue.pop();
      pthread_cond_signal(&_cond_pro);
      pthread_mutex_unlock(&_mutex);
    }
};
void *Consumer(void *arg) {
  BlockQueue<int> *p = (BlockQueue<int>*)arg;
  while (1) {
    int data;
    p -> Pop(&data);
    printf("Consumer get data: %d\n", data);
  }
}
void *Producer(void *arg) {
  BlockQueue<int> *p = (BlockQueue<int>*)arg;
  int data = 1;
  while (1) {
    p -> Push(data);
    printf("Producer put data: %d\n", data);
    ++data;
  }
}
void Test() {
  int ret;
  pthread_t con_tid[CONSUMER], pro_tid[PRODUCER];
  BlockQueue<int> q;
  //Create consumer threads 
  for (int i = 0; i < CONSUMER;  ++i) {
    pthread_create(&con_tid[i], NULL, Consumer, (void*)&q);
    if (ret != 0) {
      std::cout<<"Create consumer threads error!"<<std::endl;
      return;
    }
  }
  //Create producer threads 
  for (int i = 0; i < PRODUCER;  ++i) {
    pthread_create(&pro_tid[i], NULL, Producer, (void*)&q);
    if (ret != 0) {
      std::cout<<"Create producer threads error!"<<std::endl;
      return ;
    }
  }
  //wait threads 
  for (int i = 0; i < CONSUMER; ++i) {
    pthread_join(con_tid[i], NULL);
  }
  for (int i = 0; i < PRODUCER; ++i) {
    pthread_join(pro_tid[i], NULL);
  }
}
int main() {
  Test();
  return 0;
}


实现效果:


1.png


2.基于环形队列、信号量的实现


基于线程安全的环形队列、信号量,实现生产者与消费者模型。


相关文章
|
算法
m基于OFDM+QPSK和LDPC编译码以及MMSE信道估计的无线图像传输matlab仿真,输出误码率,并用图片进行测试
MATLAB2022a仿真实现了无线图像传输的算法,包括OFDM、QPSK调制、LDPC编码和MMSE信道估计。OFDM抗频率选择性衰落,QPSK用相位表示二进制,LDPC码用于前向纠错,MMSE估计信道响应。算法流程涉及编码、调制、信道估计、均衡、解码和图像重建。MATLAB代码展示了从串行数据到OFDM信号的生成,经过信道模型、噪声添加,再到接收端的信道估计和解码过程,最终计算误码率。
213 1
|
8月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
存储 算法 C++
C++ STL精通之旅:向量、集合与映射等容器详解
C++ STL精通之旅:向量、集合与映射等容器详解
354 0
|
缓存 NoSQL Java
使用Java构建高效的分布式缓存系统
使用Java构建高效的分布式缓存系统
|
NoSQL Redis
Redis主从结构,主库宕机,解决
Redis主从结构,主库宕机,解决
99 0
|
存储 缓存 JavaScript
React实战精讲(React_TS/API)
TS_React:使用泛型来改善类型 TS_React:Hook类型化 TS_React:类型化事件回调 React API
197 0
React实战精讲(React_TS/API)
|
Java 应用服务中间件 Apache
拆解Tomcat10: (二) 在Idea中调试最新的Tomcat10源码(二)
拆解Tomcat10: (二) 在Idea中调试最新的Tomcat10源码
484 0
拆解Tomcat10: (二) 在Idea中调试最新的Tomcat10源码(二)
深入学习checkbox类型的input元素
先看 一段选中所有页面check类型的代码 $("#SelectBtn").click(function(){var state=$("#SelectAll").attr("checked");if(state != true){ selectAll() $("#SelectAll").
777 0
|
开发工具 git 开发者
Git详解之Git分支
Git 分支 几乎每一种版本控制系统都以某种形式支持分支。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。在很多版本控制系统中,这是个昂贵的过程,常常需要创建一个源代码目录的完整副本,对大型项目来说会花费很长时间。
1107 0

热门文章

最新文章