Linux之生产者与消费者模型

Linux-生产者消费者模型 生产者消费者模型一级目录二级目录三级目录一级目录 一级目录 二级目录 三级目录 一级目录 阅读详情

今天讲下Linux里一个很重要的概念 “生产者与消费者模型” :

1.生产者与消费者模型的概念

生产者于消费者模型其实很常用,因为在实际开发中经常会遇到这种情况就是,一个模块负责生产
数据,而另一个模块负责处理数据,在这里就可以认为这个生产数据的模块就充当了生产者的角色
而这个处理数据的模块就充当了消费者的角色,而生产者生产的数据需要一个地方存储,就可以
是一个仓库,这个仓库是练习生产者与消费者的中介。

关系图如下:
在这里插入图片描述
过程就是生产者将生产的数据放到仓库中,消费者要的时候就从里面取,仓库就可以先理解是一个缓冲区,不是真正意义上的仓库!

2.了解生产者与消费者模型一定要记住下面三点

1)一个场所

一个场所指的就是这个仓库,仓库可以用来存数据也可以取数据

2)两个角色

两个角色就指的是生产者与消费者
生产者生产数据放到仓库中
消费者从仓库中取数据

3)三种关系

生产者与生产者的互斥关系
解释:两个生产者不能同时生产一个数据
消费者与消费者的互斥关系
解释:两个消费者不能同时消费一个数据
生产者与消费者的同步与互斥关系
解释:生产者生产的时候消费者不能消费(互斥)
生产者生产数据后消费者消费(同步)

同步互斥概念请看我的另一篇博文:
https://blog.youkuaiyun.com/Python_programer/article/details/90248090

3.生产者与消费者模型的功能

1)解耦和

如果没有生产者与消费者模型的话,生产者就只能靠调用某个函数和消费者练习,那么生产者
与消费者之间就会产生依赖(耦合),但是如果消费者的代码改变后,那么就会影响到生产者
的耦合性(依赖),所以使用生产者与消费者模型后,二者之间就没有那种直接的依赖关系,
而是靠一个缓冲区(仓库)联系起来,相对变得独立(解耦)。

2)支持忙闲不均

如果是生产者调用消费者的某个方法,那么很可能出现方法还没调用完毕,生产者就只能等待
这样效率大大降低,但是使用生产者与消费者模型后就不会出现这种情况,消费者并不关心消
费者的情况,而是关注缓冲区是否有数据,生产者只需要生产数据放到缓冲区内,不需要关系消费者什么时候取走。

3)支持并发

当生产者生产数据快的话,他不需要担心消费者什么时候取走,只需要放到缓冲区内,只关注缓冲区数据满了没有,而消费者如果生产的慢的话,不要担心,消费者还可以从缓冲区内取已经生产好的数据,多个生产者,消费者可以同时进行操作。

队列实现生产者与消费者模型:

实现代码

  1 #include<iostream>
  2 #include<queue>
  3 #include<pthread.h>
  4 
  5 //手撕生产者与消费者模型
  6 //一个场景,三种关系,两个角色
  7 //场景:线程安全队列
  8 //生产者向队列里放数据,消费者从里面取数据
  9 
 10 class BlockQueue
 11 {
 12     public:
 13     BlockQueue(int cap = 10):capacity(cap){
 14         pthread_cond_init(&productor,NULL);
 15         pthread_cond_init(&customor,NULL);
 16         pthread_mutex_init(&mutex,NULL);
 17     }
 18     ~BlockQueue(){
 19         pthread_cond_destroy(&productor);
 20         pthread_cond_destroy(&customor);
 21         pthread_mutex_destroy(&mutex);
 22     }
 23     bool QueuePush(int data){   //生产者向队列里放数据,设计临界资源访问首先得加锁
 24         QueueLock(); 
 25         while(QueueIsFull()){  //如果满了的话,生产者等待,这里必须用while,如果用if的话,他会等待,但是等待后依旧会往下走所以是不正确的
 26             ProductorWait();
 27         }
 28         queue.push(data);     //否则放入数据
 29         CustomorWakeUp();     //唤醒消费者
 30         QueueUnLock();        //临界资源访问完后解锁
 31         return true;
 32     }
 33     bool QueuePop(int* data){    //消费者从队列里取数据
 34         QueueLock();
 35         while(QueueIsEmpty()){
 36             CustomorWait();
 37         }
 38         *data = queue.front();
 39         queue.pop();
 40         ProductorWakeUp();
 41         QueueUnLock();
 42         return true;
 43     }
 44     private:
 45     void QueueLock(){
 46         pthread_mutex_lock(&mutex);
 47     }
 48     void QueueUnLock(){
 49         pthread_mutex_unlock(&mutex);
 50     }
 51     void CustomorWait(){
 52         pthread_cond_wait(&customor,&mutex);
 53     }
 54     void CustomorWakeUp(){
 55         pthread_cond_signal(&customor);
 56     }
 57     void ProductorWait(){
 58         pthread_cond_wait(&productor,&mutex);
 59     }
 60     void ProductorWakeUp(){
 61         pthread_cond_signal(&productor);
 62     }
 63     bool QueueIsFull(){
 64         return (queue.size()==capacity);
 65     }
 66     bool QueueIsEmpty(){
 67         return queue.empty();
 68     }
 69     private:
 70     std::queue<int> queue;
 71     int capacity;
 72     pthread_mutex_t mutex;
 73     pthread_cond_t productor;
 74     pthread_cond_t customor;
 75 };
 76 
 77 void* pth_customor(void* arg)   //消费者线程创建入口函数
 78 {
 79     BlockQueue *q = (BlockQueue*) arg;
 80     while(1)
 81     {
 82         int data;
 83         q->QueuePop(&data);
 84         std::cout<<"customor get data"<<data<<std::endl;
 85     }
 86     return NULL;
 87 }
 88 
 89 void* pth_productor(void* arg)     //生产者线程创建入口函数
 90 {
 91     BlockQueue *q = (BlockQueue*) arg;
 92     int i=0;
 93     while(1)
 94     {
 95         std::cout<<"productor put data"<<i<<std::endl;
 96         q->QueuePush(i++);
 97     }
98     return NULL;
 99 }
100 
101 int main()
102 {
103     pthread_t ctid[3],ptid[3];
104     BlockQueue q;
105     int ret;
106     for(int i = 0;i<3;i++)
107     {
108         ret = pthread_create(&ctid[i],NULL,pth_customor,(void*)&q);
109         if(ret!=0){
110             std::cout<< "customor not exist!\n" <<std::endl;
111         }
112     }
113     for(int i = 0;i<3;i++)
114     {
115         ret = pthread_create(&ptid[i],NULL,pth_productor,(void*)&q);
116         if(ret!=0){
117             std::cout<< "productor not exist!\n" <<std::endl;
118         }
119     }
120     for(int i = 0;i<3;i++){              //线程等待
121         pthread_join(ctid[i],NULL);
122     }
123     for(int i = 0;i<3;i++){
124         pthread_join(ptid[i],NULL);
125     }
126     return 0;
127 }

SAP PS 收入确认方法配置清单(成本推导收入 / 项目进度推导收入) 摘要:本文详细介绍了SAPPS模块中两种收入确认方法的配置流程:成本推导收入(成本比例法)和项目进度推导收入(里程碑法)。通过事务码OKG1-OKG5等关键配置步骤,分别实现基于累计成本比例和里程碑完成权重的收入确认逻辑。文章对比了两种方法的适用场景和管控要点:成本法适用于成本与进度强相关的项目,需严控预计总成本;进度法则依赖明确的里程碑验收。同时提供了落地建议,包括项目类型绑定、数据校验和变更管控等最佳实践,为SAPPS系统收入确认功能实施提供完整指导。 阅读详情

相关推荐

elmos 524系列芯片笔记

芯片的工作工作原理:集成芯片Elmos524.03有发射回路和接收回路,手册有关的内部原理图,大致如下: 芯片会产生固有频率的电压信号,信号通过引脚DRV1、2输出给外部压电陶瓷片,产生固定频率的机械波,也就是所谓的超声波,超声波遇到障碍物时会反射,反射信号经过AINS、D引脚进入芯片,在芯片内部先后经过GAIN放大,滤波然后进入比较器,滤波后的信号(signal)同预先设定的阈值(threshold)比较产生信号输出。此信号最终会连接MCU处理器,需要重点关注。 基于这个内部的工作原

qq_38230916的博客 2485

Linux下实现生产者——消费者模型(代码)

涉及到的知识点: 链表操作、互斥量、条件变量、线程 代码说明: 代码是在Linux环境下运行,主要思路是在主函数中创建两个线程:生产者和消费者,将生产的产品保存在链表中。当没有产品时,消费者睡眠, 直到被生产者唤醒,当产品达到20个,生产者睡眠,知道被消费者唤醒。 实例代码 #include<stdlib.h> #include<assert.h> #include&l......

weixin_42031299的博客 4894

ORCAD原理图关联封装时出现ERROR(ORCIS-6245)、ERROR(ORCIS-6013)问题

1、当你进行如下操作时: 系统先是提示你出现ERROR(ORCIS-6245)然后再确定后再出现ERROR(ORCIS-6013)问题 是由于你的数据库的路径不对。 具体操作方法如下:1、先找到你的CAPTURE.INI文件。 2、用记事本打开CAPTURE.INI。找到下图路径 3、在你的Orcad capture CIS原理图软件中点击 Options------>CIS con...

weixin_42304393的博客 2万+

Linux--生产者--消费者模型

Linux--生产者--消费者模型--BlockQueue--RingQueue队列的实现--线程池的模拟实现--读者 写者模型简介

c-and-c++ It*s my life 856

深入理解梅尔刻度、梅尔滤波器组和梅尔时频谱图

读取一段音频,使用短时傅里叶变换,得到普通的时频谱图,然后绘制梅尔滤波器组,值得注意的是,librosa的梅尔滤波器组函数还带有权重归一化功能,即对一个三角形滤波器的每个权重,都除以该三角形的面积,如果不希望进行该归一化,设置参数。从公式可见,对数部分可以以自然对数为底数,也可以以10为底数,不同的底数对应不同的系数,要确定当前的系数,只需要代入(1000Hz, 1000mel)即可。其中,m是当前滤波器的序号,表征了当前的时间段,k是当前频率的序号,表征了当前正在对哪一频率的。

DEDSEC_Roger的博客 1万+

半桥LLC谐振变换器及同步整流MATLAB仿真(一)

LLC工作原理详细解析,工作过程详细拆解

qq_55203246的博客 3万+

Linux生产者消费者模型

生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题生产者和消费者彼此之间不直接通讯,而通过这个容器来通讯,所以生产者生产完数据之后不用等待消费者处理,直接将生产的数据放到这个容器当中,消费者也不用找生产者要数据,而是直接从这个容器里取数据,这个容器就相当于一个缓冲区,平衡了生产者和消费者的处理能力,这个容器实际上就是用来给生产者和消费者解耦的。

裙下的霸气的博客 634

带硬约束的物理信息神经网络(PINN with Hard Constraint)示例及代码

本文以一个案例介绍了带硬约束的物理信息神经网络的原理及实现步骤。

m0_72768523的博客 5357

【Linux】生产者 消费者模型

针对上述情况,将if判断改为while循环,每一次被唤醒都要被检测,只有当队列真的是不满的情况,才会进行push。发生休眠实际上就是线程切换,当线程从休眠状态被唤醒时,因为是从临界区被切走的,所以继续从临界区内部执行。供货商可以集中生产的一大批的商品 放到超市中,让消费者随时随地来买,供货商就不生产了。如:若超市火腿肠满了,就应该让消费者先消费,若超市没有火腿肠了,就应该让生产者先生产。若队列中没有数据存在,则不该让消费者消费,若队列中数据满了,不该让生产者进行生产。

qq_62939852的博客 1036

一条时间轴上的商品供给:商品供给域事件全景、八大子域事件清单与事件契约规范的工程推演

本文以虚构连锁零售企业“青禾鲜市”为例,用事件风暴重新梳理商品供给域:先剖析同词异义、状态模糊、隐式依赖与被动兜底四类冲突,再以时间轴、八条子域泳道与关键事件铺出全景地图,确立一个事件只有一个户口;随后为总店商品、门店商品、价格、库存、质量、标签、变更通知与操作日志列出聚合、事件、命令与策略,并统一命名、信封结构、版本与幂等规范。程序体检把初稿14个问题清零,仿真显示按聚合版本号更新可售视图可将误判从两位数百分比降到0.019%。文末给出四轮工作坊节奏与新品引入、全国调价、批次召回走查剧本。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 5万+

18、探索隐私工程技术的前沿:从理论到实践

本文深入探讨了隐私工程技术的核心概念、关键技术及其应用场景,分析了加密技术、访问控制和用户界面设计等在隐私保护中的作用,并结合数据库保护、物联网设备等实际场景进行阐述。同时,文章还讨论了隐私工程技术面临的挑战与未来发展趋势,提出了数据最小化原则、差分隐私、隐私增强技术等优化策略以及隐私设计、隐私影响评估等最佳实践,最后展望了新兴技术对隐私保护的影响及法规推动下的发展方向。

weixin_35307279的博客 373

生产者消费者模型

将上述场景例比到我们实际的软件开发过程中,经常会见到这样一幕:代码的某个模块负责生产数据(供货商),而生产出来的数据却不得不交给另一模块(消费者)来对其进行处理,在这之间我们必须要有一个类似上述超市的东西来存储数据(超市),这就抽象除了我们的生产者/消费者模型。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。

kalvin_y_liu的博客 6940

【tessy】软件环境配置:Keil C51 Keil uVision UVSC (Default)

本文详细说明了tessy软件如何配置【Keil C51 Keil uVision UVSC (Default)】环境,具体操作步骤和注意事项

qq_37282365的博客 600

【Linux】生产者消费者模型

🍁 🍃 🍂 🌿。

m0_60338933的博客 1903

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Linux——生产者消费者模型

摘要:生产者消费者模型解析 生产者消费者模型是一种经典的并发编程模型,通过引入缓冲区(超市)实现生产者和消费者的解耦。该模型提高了效率,支持忙闲不均,并通过互斥和同步机制保证线程安全。模型包含三种关系:生产者之间互斥、消费者之间互斥、生产者和消费者之间互斥+同步。文中实现了一个基于阻塞队列的版本,详细介绍了队列满/空时的阻塞机制、条件变量的使用以及伪唤醒问题的解决方法(使用while而非if判断)。最后给出了阻塞队列类的核心代码实现,包括入队、出队操作和线程同步机制。

二哈的博客 1235

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

【Linux多线程】生产者消费者模型

本篇博客将会介绍Linux多线程中一个非常重要的模型——生产者消费者模型

m0_74215144的博客 1612

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【Linux线程】Linux多线程实践:深入生产者消费者模型

生产者消费者模型描述了一个或多个生产者线程生成数据,并将其放入缓冲区,同时一个或多个消费者线程从缓冲区中取出数据进行处理的过程。这种模式不仅有效地实现了数据的生成与处理之间的解耦,还通过引入缓冲区来平衡生产者和消费者之间的速度差异,从而提高了系统的整体效率和稳定性

EterNity_TiMe_的计算机学习之路 2857

Linux下的生产者消费者模型模型

概念引入 linux下的生产者消费者模型举例说明就像我们在超市买东西,那么我们就是消费者,我们所消费商品的供货商显而易见就是生产者了,而其中将消费者和生产者联系起来的超市就是一个交易场所。将上述场景类比到我们实际的软件开发过程中,代码的某个模块负责生产数据(供货商),而生产出来的数据却不得不交给另一模块(消费者)来对其进行处理,在这之间我们必须要有一个类似上述超市的东西来存储数据(超市),这就抽象

blight_888的博客 569

Linux 生产者消费者模型

生产者和消费者彼此之间不直接通讯,而通过这个容器来通讯,所以,这个容器就相当于一个缓冲区,平衡了生产者和消费者的处理能力,这个容器实际上就是用来给生产者和消费者解耦的。

m0_73634434的博客 1203

Linux多线程——生产者消费者模型

生产者消费者模型是一种经典的多线程同步机制,通过缓冲区解耦生产者和消费者。本文介绍了基于阻塞队列和环形队列的两种实现方式。阻塞队列使用互斥锁和条件变量保证线程安全,当队列满时阻塞生产者,队列空时阻塞消费者。环形队列则利用信号量机制,通过空间下标取模实现循环存取,生产者和消费者可以并发执行。两种方案各有优劣:阻塞队列确保数据顺序性但可能引发死锁,环形队列性能更高但允许数据覆盖。文章通过代码示例展示了单/多生产消费场景的实现,并分析了不同场景下的适用性选择。该模型有效提高了系统并发处理能力,是任务调度和数据共享

2401_83603768的博客 1139

Linux生产者消费者模型(31)

Hello,我们继续来学习Linux!!!终于马上就能结束系统了!欧耶!再撑一下,Linux的网络部分终于要结束了!

tan180°的博客 1523
上一篇: C++实现日期类
下一篇: Linux之posix信号量
Python_programer
博客等级 码龄9年 25粉丝 57原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值