Linux--生产消费模型

线程系列:
Linux–线程的认识(一)
Linux–线程的分离、线程库的地址关系的理解、线程的简单封装(二)
线程的互斥:临界资源只能在同一时间被一个线程使用

生产消费模型

生产消费模型是多线程编程和分布式系统中的一个经典概念,它描述了生产者和消费者之间的交互方式。在这个模型中,生产者负责生成数据或任务,而消费者则负责处理这些数据或任务。这种模型在处理并发和异步操作时非常有用,尤其是在需要平衡生产速率和消费速率的情况下。

基本概念

生产者(Producer):负责生成数据或任务的实体。在多线程环境中,这通常是一个线程或一组线程。
消费者(Consumer):负责处理数据或任务的实体。同样,这也可以是一个线程或一组线程。
缓冲区(Buffer):生产者和消费者之间的中间存储区域,用于临时存放生产者生成的数据,直到消费者准备好处理它们。

工作原理

  • 生产者:当生产者生成数据时,它将数据放入缓冲区。如果缓冲区已满,生产者可能需要等待或停止生产,直到缓冲区有足够的空间。
  • 消费者:消费者从缓冲区取出数据进行处理。如果缓冲区为空,消费者可能需要等待或暂停,直到有新的数据可用。

关键技术

  • 同步机制:如信号量、互斥锁、条件变量等,用于控制对共享资源的访问,确保生产者和消费者不会同时访问或修改缓冲区。
  • 阻塞队列:一种特殊的队列,当尝试添加或移除元素时,如果队列已满或为空,操作会被阻塞,直到条件满足。

应用场景

  • 并发编程:在多线程环境中,生产消费模型可以帮助有效地管理资源和任务分配。
  • 分布式系统:在网络服务中,如消息队列系统,生产者可以是发送消息的服务,消费者则是接收并处理这些消息的服务。

生产消费模型是理解和实现高效并发和分布式系统的关键,通过合理设计和优化,可以显著提高系统的性能和稳定性

单生产-单消费

BlockQueue.hpp: 阻塞队列
阻塞队列是一种支持两个附加操作的队列。这两个附加的操作是:当队列为空时,获取元素的线程会等待队列变为非空;当队列已满时,存储元素的线程会等待队列可用。

#ifndef __BLOCK_QUEUE_HPP__
#define __BLOCK_QUEUE_HPP__#include <iostream>
#include <string>
#include <queue>
#include <pthread.h>
using namespace std;template <class T>
class BlockQueue 
{
public:BlockQueue(int cap) :_cap(cap),_product_wait_num(0),_consum_wait_num(0){pthread_mutex_init(&_mutex,nullptr);pthread_cond_init(&_product_cond,nullptr);pthread_cond_init(&_consum_cond,nullptr);}void Enqueue(T& in)//生产者所用接口{pthread_mutex_lock(&_mutex);//对临界资源开启保护while(IsFull())//当队列存满后需要让生产者停止生产,进入阻塞状态{_product_wait_num++;pthread_cond_wait(&_product_cond,&_mutex);_product_wait_num--;}//开始生产_block_queue.push(move(in));//让消费者来消费if(_consum_wait_num>0)pthread_cond_signal(&_consum_cond);pthread_mutex_unlock(&_mutex);}void Pop(T* out){pthread_mutex_lock(&_mutex);//对临界资源开启保护while(IsEmpty())//当队列空缺后需要让消费者停止消费,进入阻塞状态{_consum_wait_num++;pthread_cond_wait(&_consum_cond,&_mutex);_consum_wait_num--;}//进行消费*out=_block_queue.front();_block_queue.pop();//通知生产者if(_product_wait_num>0)pthread_cond_signal(&_product_cond);pthread_mutex_unlock(&_mutex);}~BlockQueue(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_product_cond);pthread_cond_destroy(&_consum_cond);}
private:bool IsFull(){return _block_queue.size() == _cap;}bool IsEmpty(){return _block_queue.empty();}queue<T> _block_queue;//阻塞队列int _cap; //总上限pthread_mutex_t _mutex; //互斥锁pthread_cond_t _product_cond; //生产者的条件变量pthread_cond_t _consum_cond; //消费者的条件变量int _product_wait_num;int _consum_wait_num;
};
#endif

代码解释:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
main.cc: 主函数
在这里插入图片描述

#include"BlockQueue.hpp"
#include"Thread.hpp"
#include<string>
#include<vector>
#include<unistd.h>using namespace ThreadMdule;
int a=10;
//生产者
void Productor(BlockQueue<int>& bq)
{int cnt=1;while (true){bq.Enqueue(cnt);std::cout << "Productor product data is : " << cnt << " addr: " << &bq << std::endl;cnt++;//sleep(3);}
}
//消费者
void Consumer(BlockQueue<int>& bq)
{while (true){int data;bq.Pop(&data);std::cout << "Consumer Consum data is : " << data << " addr: " << &bq << std::endl;sleep(5);}
}
//执行创建线程的函数
void StartComm(std::vector<Thread<BlockQueue<int>>> *threads, int num, BlockQueue<int> &bq, func_t<BlockQueue<int>> func)
{for (int i = 0; i < num; i++){std::string name = "thread-" + std::to_string(i + 1);//将线程放入threads中,记录信息threads->emplace_back(func, bq, name);threads->back().start();}
}
void StartProductor(vector<Thread<BlockQueue<int>>>* threads,int num,BlockQueue<int>& bq)
{StartComm(threads,num,bq,Productor);
}
void StartConsumer(vector<Thread<BlockQueue<int>>>* threads,int num,BlockQueue<int>& bq)
{StartComm(threads,num,bq,Consumer);
}void WaitAllThread(std::vector<Thread<BlockQueue<int>>> &threads)
{for (auto &thread : threads){thread.Join();}
}
int main()
{BlockQueue<int>* bq=new BlockQueue<int>(5);vector<Thread<BlockQueue<int>>> threads;//用threads来记录线程的信息StartProductor(&threads,1,*bq);StartConsumer(&threads,1,*bq);WaitAllThread(threads);
}

在这里插入图片描述
在这里插入图片描述

细节:

在这里插入图片描述
在这里插入图片描述

多生产-单消费

这里在上面主函数代码上更改生产者的数量即可。

直接验证:
在这里插入图片描述

这里用任务类来作为阻塞队列的任务,让生产者产出对应任务,消费者来解决任务;生产出来的任务先放入阻塞队列作为缓冲;

#include<iostream>
#include<string>
#include<functional>
using namespace std;class Task
{
public:Task(){}Task(int a,int b): _a(a),_b(b),_result(0){}void Excute(){_result=_a+_b;}string ResultToString(){return to_string(_a) + "+"+to_string(_b)+"="+to_string(_result);}string DebugToString(){return to_string(_a) + "+" + to_string(_b) + "= ?";}
private:int _a;int _b;int _result;
};

//类型
在这里插入图片描述
//生产者:
在这里插入图片描述
//消费者:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/44229.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我们水冷使制动电阻功率密度成倍增加-水冷电阻设计工厂

先进陶瓷 我们后来发现工业应用中对占用空间最小的水冷电阻器的工业需求&#xff0c;推出了适用于中压工业应用的水冷电阻器。它的特点是两块由具有特殊性能的先进陶瓷制成的板。 使用工业电驱动装置的一个重要好处是&#xff0c;可靠的再生和动态制动系统可以补充或取代传统…

Llama2 训练指南

Llama2 是一个基于 Python 的机器学习框架&#xff0c;旨在帮助开发者快速构建和部署机器学习模型。下面是 Llama2 训练指南&#xff0c;旨在帮助您了解如何使用 Llama2 训练模型。 概述 Llama2 提供了多种方式来训练模型&#xff0c;包括使用 Keras 和 TensorFlow。下面是在…

Laravel :如何将Excel文件导入数据库

文章目录 一、前提二、使用2.1、新建一个导入文件2.2、新建一个控制器和方法,调用导入文件2.3、 新建一个页面&#xff0c;支持文件上传 一、前提 想要将excel内容入库&#xff0c;laravel有扩展可以使用,常用的扩展是maatwebsite/excel&#xff0c;安装步骤参考上一篇&#x…

力扣 202快乐数

快乐数这题有两个关键 一个是求n的 各个位上平方和 另一个是判断是否为快乐数的依据是是否在哈希表中找到已经出现过的数 1求各个位上平方和方法 定义sum sum N除以十取余的平方和 n/10 循环终止条件是n0 2查找一个数是否出现&#xff0c;用哈希表unordered_set &…

Mosh|SQL教程第四弹(未完)

SQL有很多自带的内聚的函数&#xff08;MAX、MIN、AVG、SUM、COUNT&#xff09; 一、聚合函数&#xff08;Aggregate Functions&#xff09; 这里的括号可以写列名也可以写表达式,下面是一个练习&#xff1a; 二、GROUP BY子句 统计2019-07-01以后每个客户的总销售额 注意这…

result.h

#ifndef ASYNCIO_RESULT_H #define ASYNCIO_RESULT_H#include <asyncio/exception.h> #include <variant> #include <optional> namespace ASYNCIO_NS {// 结果类封装&#xff08;不是协程函数的返回类型&#xff09; template<typename T> struct Res…

Javaweb11-Filter过滤器

Filter过滤器 1.Filter的基本概念&#xff1a; 在Java Servlet中&#xff0c;Filter接口是用来处理HttpServletRequest和HttpServletResponse的对象的过滤器。主要用途是在请求到达Servlet之前或者响应离开Servlet之前对请求或响应进行预处理或后处理。 2.Filter常见的API F…

探展2024世界人工智能大会之合合信息扫描黑科技~

文章目录 ⭐️ 前言⭐️ AIGC古籍修复文化遗产焕新⭐️ 高效的文档图像处理解决方案⭐️ AIGC扫描黑科技一键全搞定⭐️ 行业级的大模型加速器⭐️ 结语 ⭐️ 前言 大家好&#xff0c;我是 哈哥&#xff08;哈哥撩编程&#xff09; &#xff0c;这次非常荣幸受邀作为专业观众参…

【常用知识点-Java】读取Properties文件

Author&#xff1a;赵志乾 Date&#xff1a;2024-07-11 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 简介 .properties文件是一种简单的文本文件&#xff0c;用于存储键值对&#xff0c;其每个键值对占一行&#xff0c;且键和值之间用…

力扣题解( 最长递增子序列的个数)

673. 最长递增子序列的个数 给定一个未排序的整数数组 nums &#xff0c; 返回最长递增子序列的个数 。 注意 这个数列必须是 严格 递增的。 思路&#xff1a; 用一个maxlen表示当前最长递增数组的长度&#xff0c;maxcount表示最大长度。当进下标为i的元素时&#xff0c;将…

重磅!新公司法正式实施,这些变化你必须知道! ️

新公司法来了&#xff01;企业设立和经营必知的关键变动 &#x1f3db;️&#x1f680; 大家好&#xff0c;我是猫头虎&#xff0c;科技自媒体博主。今天我们来聊聊一件大事——新公司法的实施&#xff0c;这对企业设立和经营带来了哪些重大影响&#xff1f;跟着我&#xff0c…

【DDIM】DENOISING DIFFUSION IMPLICIT MODELS【论文精读】【视频讲解】【公式推导】

论文&#xff1a;DENOISING DIFFUSION IMPLICIT MODELS&#xff08;https://arxiv.org/abs/2010.02502&#xff09; B站视频链接 DDIM论文精讲视频 去噪扩散隐模型的论文精读&#xff0c;涉及本文的大部分公式逐步推导。总计3小时的详细论文讲解。 讲解详细对应文档 DDIM视频…

聊聊mysql

记录那些坑 本文会持续更新&#xff0c;陆续更新有关mysql技术内幕、实战优化、面试技巧。 文章目录 前言索引BTree之聚集索引BTree之辅助索引BTree之联合索引BTree之覆盖索引 使用到的工具1、py_innodb_page_info工具2、hexdump工具 总结 前言 重中之重的MySql数据库 mysql…

模拟人机猜数游戏

设计目的 1、加深学生对该课程基础知识和基本理论的理解和掌握&#xff0c;培养学生综合运用所学知识独立 分析和解决问题的能力; 2、培养学生在计算机软硬件开发、理论计算、查阅资料等方面的能力&#xff0c;使学生逐步树立正 确的设计思想; 3、加强理论联系实际&#xff0c…

邦芒支招:职场高效沟通的6个秘诀

​​俗话说得好“良言一句三冬暖&#xff0c;恶语伤人六月寒。”无论在什么单位&#xff0c;社会上竟是形形色色的人等&#xff0c;人过一百&#xff0c;形形色色。每个人都想得到他人赏识、挥洒才华、争得提升。但是&#xff0c;要和陌生的人融洽相处、沟通合作&#xff0c;是…

Android 蓝牙语音通话调试

首先要清楚蓝牙语音通话属于蓝牙得哪一个协议 1、HEADSET 耳机和免提模式,用于蓝牙耳机 2、A2DP (advanced audio distribution profile)高级音频及立体声规范,包括A2DP SINK和A2DP SOURCE 3、HEALTH 健康设备规范,和一些健康设备进行通信 4、OPP (object push profi…

概率论期末速成(知识点+例题)

考试范围 一&#xff1a; 事件关系运算性质全概率公式、贝叶斯公式古典概型 二&#xff1a; 离散分布律连续密度函数性质 -> 解决三个问题&#xff08;求待定系数、求概率、求密度函数&#xff09;分布函数 -> 解决三个问题常用分布&#xff08;最后一节课的那几个分…

手电筒的光能飞到宇宙尽头吗

如果我们打开手电筒向夜空照一秒再关掉&#xff0c;我们将会看到&#xff0c;在关掉手电筒的一瞬间&#xff0c;手电筒发出的光束也会消失&#xff0c;那么&#xff0c;它发出的光哪去了呢&#xff1f;下面我们就来聊一下这个话题。实际上&#xff0c;我们看到的光束&#xff0…

Spark SQL 概述

Spark SQL 概述 Spark SQL 是 Apache Spark 的一个模块&#xff0c;专门用于处理结构化数据。它集成了 SQL 查询和 Spark 编程的强大功能&#xff0c;使得处理大数据变得更加高效和简便。通过 Spark SQL&#xff0c;用户可以直接在 Spark 中使用 SQL 查询&#xff0c;或者使用 …

ubuntu16.04安装低版本cmake(安装cmake安装)

文章目录 ubuntu16.04安装低版本cmake&#xff08;安装cmake安装&#xff09;1. **下载并解压CMake压缩文件**&#xff1a;- 首先&#xff0c;你需要从CMake的官方网站或其他可靠来源下载cmake-2.8.9-Linux-i386.tar.gz文件。- 然后在终端中使用以下命令解压文件&#xff1a; 2…