《操作系统》-生产者消费者问题

article/2025/11/10 2:44:59

什么是生产者消费者问题?

系统中有一组生产者进程和一组消费者进程。生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个进程并使用,那么他们之间具有这样一层关系
生产者、消费者共享一个初始为空、大小为n的缓冲区。
只有缓冲区没满时,生产者才能把产品放入缓冲区。否则必须等待 (缓冲区没满->生产者生产)
只有缓冲区不空时,消费者才能从中取出产品,否则必须等待 (缓冲区不空->消费者消费)
缓冲区是临界资源,各进程访问时要求互斥 (互斥访问)
在这里插入图片描述

对生产者消费者问题进行分析

由上面的描述可知:要执行生产者生产操作的前提条件是缓冲区没满,而执行消费者消费的前提条件是缓冲区不空。上一篇文章我们说过如何用信息量机制来实现进程的同步,还不熟悉的小伙伴可以参考一下这篇文章如何用信息量机制实现进程互斥、进程同步和前驱关系
在前操作之后对相应的同步信息量执行V操作
在后操作之前对相应的同步信息量执行P操作
所以他们之间是这样的关系
在这里插入图片描述
代码可以这么来写

semaphore mutex = 1; //互斥信号量,实现对缓冲区的互斥访问
semaphore empty = n; //同步信号量,表示空闲缓冲区的数量
semaphore full = 0; //同步信号量,表示产品的数量,也即非空缓冲区的数量

生产者生产

producer (){
while(1){
生产一个产品;
P(empty);
P(mutex);
把产品放入缓冲区;
V(mutex);
V(full);
} }

P(mutex)V(mutex)实现进程的互斥访问,P(empty)实现让缓冲区没满作为生产者生产的前操作,即当empty==0时即无空闲缓冲区数量时,让消费者消费作为生产者生产的前操作
V(full)实现让缓冲区不空作为消费者消费的前操作,即当full==0时即缓冲区全为空时,让生产者生产作为消费者消费的前操作
消费者消费

consumer (){
while(1){
P(full);
P(mutex);
从缓冲区取出一个产品;
V(mutex);
V(empty);
使用产品; }

P(mutex)V(mutex)实现进程的互斥访问,V(empty)实现让缓冲区没满作为生产者生产的前操作,即当empty==0时即无空闲缓冲区数量时,让消费者消费作为生产者生产的前操作
P(full)实现让缓冲区不空作为消费者消费的前操作,即当full==0时即缓冲区全为空时,让生产者生产作为消费者消费的前操作

思考:能否改变相邻P、V操作的顺序?

如果将上述的代码改为这样会产生怎样的影响呢?

producer (){
while(1){
生产一个产品;
P(mutex);// ①
P(empty);// ② 把产品放入缓冲区;
V(mutex);
V(full);
} }
consumer (){
while(1){
P(mutex);// ③
P(full);// ④ 从缓冲区取出一个产品;
V(mutex);
V(empty);
使用产品; } }

若此时缓冲区内已经放满产品,则empty=0,full=n。
则生产者在执行①操作时使mutex变为0,再执行②,由于已经没有空闲缓冲区了所以生产者会被堵塞,并且在消费者进程执行时,执行到③操作时,由于mutex为0,也会被堵塞。
这就导致了生产者在等待消费者是否空闲缓冲区,而消费者等待生产者释放临界资源的情况,生产者和消费者就这样循环等待被对方唤醒,出现了“死锁”的情况。
同样的,在缓冲区全为空的情况下,即empty=n,full=0时,按③④①的顺序执行也会发生“死锁”。
因此,统一一下:实现进程互斥的P操作要在实现进程同步的P操作之后
V操作不会导致进程堵塞,因此V操作的顺序可以调换

总结
对于生产者消费者问题的要求做一下总结
1、生产者、消费者共享一个初始值为空,大小为n的缓冲区 刚开始空闲缓冲区的数量为n,非空闲缓冲区的数量为0
2、只有缓冲区没满时,生产者才能把产品放入缓冲区。否则必须等待 同步关系,缓冲区满时,生产者要等待消费者取走产品
3、只有缓冲区不空时,消费者才能从中取出产品,否则必须等待 同步关系,缓冲区为空时,消费者要等待生产者生产
4、缓冲区是临界资源,各进程访问时要求互斥 互斥

多生产者-多消费者问题

举个例子来说明多生产者-多消费者问题
桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。用PV操作实现上述过程。
在这里插入图片描述
对于解决这种问题,我们需要进行以下步骤:
1、关系分析,找出题目中描述的各个进程,分析他们之间的同步、互斥关系
2、整理思路。根据各进程的操作流程确定P、V操作的大致顺序
3、设置信号量,设置所需要的信号量并且根据题目要求设置信号量的初值

对于上述题目我们所确立的关系为:
互斥关系:(mutex = 1)
对缓冲区(盘子)的访问要互斥地进行
同步关系:(一前一后)
1、父亲将🍎放入盘子后,女儿才能取🍎
2、母亲将🍊放入盘子后,儿子才能取🍊
3、只有盘子为空时,父亲或母亲才能放入水果

如何实现

semaphore mutex = 1; //实现互斥访问盘子(缓冲区)
semaphore apple = 0; //盘子中有几个苹果
semaphore orange = 0; //盘子中有几个橘子
semaphore plate = 1; //盘子中还可以放多少个水果
dad (){
while(1){
准备一个苹果;
P(plate);
P(mutex);
把苹果放入盘子;
V(mutex);
V(apple);} 
}mom (){
while(1){
准备一个橘子;
P(plate);
P(mutex);
把橘子放入盘子;
V(mutex);
V(orange);} 
}daughter (){
while(1){
P(apple);
P(mutex);
从盘中取出苹果;
V(mutex);
V(plate);
吃掉苹果; } 
}son (){
while(1){
P(orange);
P(mutex);
从盘中取出橘子;
V(mutex);
V(plate);
吃掉橘子;} 
}

但在本题中其实互斥信号量可以省略,原因在于:
本题中缓冲区大小为1,在任何时候,apple、orange、plate三个同步信号量中最多只有一个是1.因此在任何时刻,最多只有一个进程的P操作不会被堵塞,并顺利地进入临界区,如何盘子的容量大于1时,互斥信号量就不能省略了


http://chatgpt.dhexx.cn/article/PYZ1whbo.shtml

相关文章

生产者-消费者问题(操作系统)

生产者-消费者问题从特殊到一般(从易到难)可以分3种形式: 一个生产者、一个消费者、一个缓冲区的问题; 一个生产者、一个消费者、n个缓冲区的问题; k个生产者、m个消费者、n个缓冲区的问题; ★当缓冲区空时,生产者可…

Java多线程——生产者消费者问题

创建多个线程去执行不同的任务,如果这些任务之间有着某种关系,那么线程之间必须能够通信来协调完成工作。 生产者消费者问题(英语:Producer-consumer problem)就是典型的多线程同步案例,它也被称为有限缓冲…

生产者-消费者问题(详解)

目录 1.问题描述 2.问题分析 3.问题实现 3.1 初始化 3.2 生产者 3.3 消费者 1.问题描述 要求如下: 只要缓冲区没满,生产者才能把产品放入缓冲区,否则必须等待。只有缓冲区不空时,消费者才能从中取出产品,否则必…

【操作系统】生产者消费者问题

生产者消费者模型 文章目录 生产者消费者模型 [toc]一、 生产者消费者问题二、 问题分析三、 伪代码实现四、代码实现(C)五、 互斥锁与条件变量的使用比较 一、 生产者消费者问题 生产者消费者问题(英语:Producer-consumer proble…

Sublime Text实现代码自动生成,快速编写HTML/CSS代码

目录 下载Sublime Text安装emmet插件常用自动生成HTML代码实例初始化页面自动补全标签配对自动添加类名和id名自动填充文本内容自动生成同级标签自动生成嵌套标签自动生成提级标签自动生成分组标签自动生成多个元素自动生成带多个属性的元素自动生成隐式标签 常用自动生成CSS代…

MybatisPlus代码自动生成

这里写自定义目录标题 前言一. 什么是 MyBatis-Plus二.MybatisPlus 代码自动生成①idea 插件生成1. 插件2.连接数据源3.生成代码 ②配置工具类生成 前言 最开始,要在 Java 中使用数据库时,需要使用 JDBC,创建 Connection、ResultSet 等&…

Simulink自动代码生成:生成代码的基本设置

Simulink自动代码生成也被称作基于模型开发(BMD),相比于传统的手写代码方式能够尽量减少人为错误。模型本身可以用于仿真,单元测试等,更便于提前发现逻辑错误。同时只要约定好模型接口,就可以多人协作&…

C语言代码自动生成工具

一、模型建模模块: 基于开源开发平台Eclipse,以图形方式创建和编辑模型元素,模型元素如下: 活动:初始活动、简单活动、复杂活动、结束活动;状态:初始状态、状态、结束状态;变迁&a…

前端代码自动生成器

场景 1.CodeFun是什么 CodeFun是一款UI 设计稿智能生成源代码的工具,支持微信小程序端、移动端H5和混合APP,上传 Sketch、PSD等形式的设计稿,通过智能化技术一键生成可维护的前端代码. 2.学习成本高吗? 对于前端工程师来说,几乎没有学习成本…

MATLAB/Simulink自动代码生成(一)

Simulink自带了种类繁多、功能强大的模块库,在基于模型设计的开发流程下,Simulink不仅通过仿真可以进行早期设计的验证,还可以生成C/C、PLC等代码直接应用于PC、MCU、DSP等平台。在嵌入式软件开发中发挥着重要的作用,本文以Simuli…

IDEA自动生成代码插件

官方介绍 基于IntelliJ IDEA开发的代码生成插件,支持自定义任意模板(Java,html,js,xml)。 只要是与数据库相关的代码都可以通过自定义模板来生成。支持数据库类型与java类型映射关系配置。 支持同时生成生…

Matlab/Simulink自动生成C代码实验

目录 0. 概要 1. Matlab /Simulink/Embedded Coder关系与区别 2. 搭建Simulink模型及仿真 2.1 搭建模型 2.2 仿真 3. 生成代码 3.1 求解器设置为定步长 3.2 安装 MinGW-w64 编译器 3.3 调出Simulink Coder 4. 工具都生成了啥呢? 0. 概要 Matlab网站提供了很多…

关于RuoYi自动代码生成功能的使用

为什么要使用代码生成? 答:因为在后端构建的过程中会有许多重复的类似的代码编写,而我们如果一个个去编写,会耗费大量时间与精力,所以我们可以设计一个功能去自动生成这些重复的,简单的代码。而若依系统就…

Mybatis Plus自动生成代码

mybatis-plus自动生成代码 一、简易生成代码二、指定生成的样式,并且不在一个模块1.父pom文件配置2.子模块pom文件配置3.准备vm文件4.设置MyBatisPlusGenerator.java5.运行MyBatisPlusGenerator.java文件6.运行sign-auth模块,解决异常 一、简易生成代码 /*** 代码生…

Simulink自动代码生成:数据类型别名自定义

在手写代码时,我们经常能看到自定义数据类型别名,例如有些代码中将计算机默认的数据类型改为我们自己习惯的名称,如图所示。 目录 一. 系统默认生成的别名二. 建立Simulink AliasType三. 修改Data Type Replacement四. 数据类型别名修改后的…

Simulink 自动代码生成原理

如下图,Simulink模型会先变成一个文本式的 .rtw 模型描述文件,然后再变成 .c,.h,最后编译为最终目标文件。 典型的 Simulink 用户通常都是,用Simulink设计好算法后,做到生成源代码这一步。然后把生成的算法的.c .h 源代…

如何自动生成SpringBoot项目代码

目录 1.RuoYi源码下载及启动若依服务1.1. RuoYi源码下载1.2. 启动若依服务 2.自动生成代码3.代码及sql文件链接 已经工作一段时间啦!首先是从后端开发开始入手的,前端也是在自学阶段(边学边问我身边的同事大佬),努力是…

Simulink自动代码生成:数据字典的建立及代码优化

在上一节《Simulink自动代码生成:生成代码的基本设置》的基础上,我们来对模型进行优化,使得生成的代码更能满足实际的需求,没看过我上一篇文章的可以点开如下链接:   Simulink自动代码生成:生成代码的基本…

推荐几个代码自动生成器

文章目录 老的代码生成器的地址:[https://www.cnblogs.com/skyme/archive/2011/12/22/2297592.html](https://link.zhihu.com/?targethttps%3A//www.cnblogs.com/skyme/archive/2011/12/22/2297592.html)1.懒猴子CG2.IT猿网3.listcode4.magicalcoder5.CodeSmith6. …

Mybatis代码自动生成

新启动的项目,数据库设计可能随时会变动,一些基础的接口,特别是xml文件和映射对象也需要变动,改动工作量大,用mybatis-plus代码自动生成工具自动生成代码,大大提高了效率 自动生成代码工具使用过程记录如下 首先手动创建一个springboot项目,可以去springboot官网上生成,也可以…