CHS_08.2.3.6_1+生产者-消费者问题

news2024/11/26 8:58:06

CHS_08.2.3.6_1+生产者-消费者问题

  • 问题描述
  • 问题分析
  • 思考:能否改变相邻P、V操作的顺序?
  • 知识回顾

在这个小节中 我们会学习一个经典的进程同步互斥的问题

问题描述

在这里插入图片描述

并且尝试用上个小节学习的p v操作 也就是信号量机制来解决这个生产者消费者问题

问题的描述是这样的 在一个系统当中 有一组生产者进程和一组消费者进程

生产者进程每次生产一个产品并且放入缓冲区 那这缓冲区其实就是用来存放数据的

一片区域 我们可以把它理解为 一个一个小格子 每个缓冲区 也就是每一个小格子里面可以放一个产品

一个 也就是一坨数据 然后消费者呢 又会从这些缓冲区当中每次取出一个产品 也就是每次

取出一头数据 那生产者和消费者这两组进程他们会共享的使用

一个初始为空 大小为n的缓冲区 也就是有n个小格子可以放n个产品

那需要注意的是 这个缓冲区是有容量限制的 它只能放五个产品

那只有缓冲区没有满的时候 生产者才可以往这个缓冲区里放入产品

比如说像这个样子 因为缓冲区大小为五所以它最多只能放入五个产品 也就五个数据

那如果缓冲区此时已经满了 但是生产者进程还想尝试往里面写数据

那生产者进程必须阻塞等待 等这个缓冲区被取空的时候 他才可以往里边

写数据那有没有发现这个条件 就是我们上小节分析的同步问题

问题分析

在这里插入图片描述

也就是说 缓冲区没满的时候
生产者才能生产 这是一对一前一后的同步关系
另外呢

消费者进程 他会从这个缓冲区里取走这些产品 就是取走这些数据 就像这个样子

那当缓冲区没满的时候 也就是有空闲的缓冲区的时候 生产者就可以继续生产

也就是说 当一个消费者从缓冲区取走数据之后 如果此时有生产者是处于阻塞状态的 那么消费者进程应该把生产者进程给唤醒

让他重新回到就绪态 不过呢 生产者进程只是回到了就绪态 这并不意味着生产者进程会立即往里边写数据

所以接下来有可能是消费者进程继续往把这些缓冲区里的数据依次取走 那需要注意的是 只有缓冲区不空的时候 也就是说只有缓冲区里有数据 有产品的时候
消费者进程才可以从缓冲区里取走数据
不然的话消费者进程就必须阻塞等待

所以其实这个条件就是第二对的同步关系 也就是只有缓冲区没空的时候 或者说缓冲区里有产品的时候

消费者才可以取走数据 才可以消费 那最后一个条件是这个缓冲区 它是一种临界资源

各个进程必须互斥的访问缓冲区 那这我们来解释一下为什么必须互斥的访问缓冲区

那假设这个系统当中此时有两个生产者进程正在并发的运行 那么第一个生产者进程在检查缓冲区的时候发现 哎 这个缓冲区此时都是空的

所以我可以挑选其中的某一片往里面写入数据 与此同时 第二个生产者进程 它也并发的运行

他也发现此时这个缓冲区都是空的 因此他也会挑选其中的一块写入数据

那假设下面的这个生产者进程往这写了一篇数据 而上面这个生产者进程他自己挑选的也是这一片区域
那接下来这个生产者进程也往这片区域冲入自己的数据 那这样的话 他就会把前面那个进程的数据给覆盖掉

所以可以看到 如果各个进程同时访问缓冲区的话 那么有可能会出现一系列的问题 比如说刚才我们提到的数据覆盖
所以缓冲区这种资源 它是一种临界资源 各个进程必须互斥的访问

那么既然需要互斥的访问 这其实就是我们之前学过的互斥的问题 那刚才我们做的这一系列分析

找出了这个问题里边所隐含的一系列的同步和互斥的关系

那第二步我们需要做的是要根据各个进程操作的流程来确定pv操作的大致顺序

那其实很简单 就是我们上个小节中提到过的 前V后P 第一对关系是只有 当
缓冲区里有产品的时候 消费者进程 它才可以消费
另外呢 只有缓冲区没满的时候
生产者进程才可以生产
所以这样的两对一前一后的同步关系 我们就需要给他们分别设置一个同步信号量
在这里插入图片描述

并且在前面这个动作完成之后 需要对这个同步信号量执行一个V操作

在后面这个动作开始之前 需要对这个同步信号量执行一个p操作 那我们一会来解释一下这两个同步信号量 它在背后的含义

那这是这两对同步关系里边pv操作的一个大致顺序 那缓冲区里有产品

这个事件是生产者进程触发的 也就说 当一个生产者进程往缓冲区里放入一个产品 放入一个数据之后
他就需要对这个信号量执行一个V操作
而当消费者进程从缓冲区里取走数据之前
它需要对这个型号量执行一个p操作
那下面的这个同步关系也一样 那除了这两对同步关系之外 我们还需要实现对缓冲区这种临界资源的互斥访问

互斥的实现其实是很简单的 我们只需要设置一个互斥信号量 mutex 并且让它的初始值为一

然后在临界区的前面和后面分别对互斥信号量执行p v操作就可以了 那接下来我们应该做的就是要确定这些信号量的初始值

对于互斥信号量来说 一般初始值就是一就像我们刚才所说的那样 而对于同步信号量来说 它的初始值 我们要看它所对应的那种资源初始值是多少

那我们来看一下这两对同步关系所对应的这种资源到底是什么呢 那先来看上面这对同步关系

消费者进程 他在消费之前需要消耗什么资源呢 需要消耗的是产品 对吧

所以他的这个p操作其实是在申请一个产品 申请一个数据

因此 full这个同步信号量 它所对应的资源应该是产品的数量

也就是非空缓冲区的数量 而从题目当中给的条件 我们知道缓冲区刚开始都是空的

也就是说 刚开始产品的数量 产品这种资源的数量应该是零因此

full这个同步信号量的初始值 我们就把它设置为零表示刚开始没有产品这种资源
而这种资源只能由生产者进程
生产了之后来释放 那再来看第二个同步信号量empty

那我们知道 生产者进程每生产一个产品 就需要消耗一个空闲的缓冲区

因此 empty这个同步信号量 它所对应的资源就应该是空闲缓冲区这种资源

它的数量就是空闲缓冲区的数量 当一个消费者进程取走了产品 也就是

做了消费的动作之后 他就可以释放一个empty 也就是释放一个空闲的缓冲区

那从题目给的条件 我们知道 刚开始缓冲区都是空的 有n个缓冲区 因此空闲缓冲区它的初始值应该是n

所以这样我们就确定了这两个同步信号量的一个初始值 那接下来就是代码的实现

生产者进程 他要做的事情就是不断的生产一个产品 并且把产品放到缓冲区
在这里插入图片描述

而消费者进程 他要做的事情就是不断的从缓冲区里取走一个产品 并且使用这个产品消费这个产品

那通过刚才的分析 我们知道 生产者进程再把产品放入缓冲区之前需要申请一个空闲的缓冲区
因此 当他放入产品之前 需要对empty这个同步信号量执行一个p操作

而当他把产品放入缓冲区之后 其实就相当于产品这一种

资源的数量加一了 或者说非空缓冲区的数量加一了 因此当它放入产品之后 需要对这个信号量执行一个V操作

表示 增加一个这种资源 而消费者进程的分析也类似当他从缓冲区取走一个产品之前
需要先对这个full变量进行一个p操作 也就是要申请消耗一个产品这种资源

而当他取走了一个产品之后 空闲缓冲区的数量就会加一因此在这个操作之后 需要对empty进行一个v操作 表示要增加一个空闲缓冲区

那这样我们就实现了两对同步关系 另外 题目中要求缓冲区必须互斥的访问 它是临界资源 所以在访问缓冲区

前后分别要对这个互斥信号量执行p和v操作 用于实现对缓冲区的互斥访问

那从这个例子当中 我们可以看到 实现互斥的p v操作 它是在同一个进程内进行的

这个进程对临界区上了锁 而当他访问完临界区之后 又需要的对这个临界区进行解锁

所以 这个pv操作是在同一个进程的代码当中实现的 而同步关系就不一样了 我们会发现

这个进程 生产者进程里边是对full变量执行了v操作 而消费者进程里边是对full变量执行了p操作

也就是对同一个变量的p v 这两个操作是分别需要在不同的两个进程之间执行的

执行v操作的这个进程会唤醒相对应的执行p操作的这个进程

那如果结合刚才我们给的这个同步关系的前驱图 就会发现

这个代码其实完全可以根据这个前驱图的关系来得出 那这大家可以自己暂停来

体会一下前V后P 那接下来我们要思考的一个问题是

能否改变相邻的pv操作的顺序呢 也就说我们刚才是先对同步信号量执行了p

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

在这里插入图片描述

再对互斥信号量执行了p 而我们现在尝试把它颠倒一下 先对这个互斥信号量执行p操作 再对同步信号量执行p操作 会发生什么情况呢

我们来看一下 假设此时这个缓冲区里边已经放满了产品 也就是empty等于零

full等于n 那此时如果生产者进程执行了一使empty的值变为了零

接着 他在执行二这一句 而此时由于empty的值已经是零了 所以生产者进程会被阻塞在二这一句 他需要等待empty这种资源

那这个时候发生了调度消费者进程 上处理机运行 那消费者进程在执行三这一句的时候

他会发现此时empty的值已经是零了 所以消费者进程他会被阻塞在三这一句

他需要等待生产者进程释放mutex 所以这就导致消费者进程也被阻塞了

那我们在捋一捋这种情况下 生产者进程 他在等待消费者进程对empty执行v操作

而消费者进程 他又在等待生产者进程对mutex执行v操作

也就说 他们在相互等待对方唤醒自己 而两个人其实都被阻塞 都在睡眠

而那这种情况就是我们之后会学习到的死锁 进程和进程之间发生了循环等待

被对方唤醒这样的一个神奇的情况 那发生了死锁之后 这两个进程就都不能往下执行 都不能推进下去了

那同样的 大家可以分析一下 当full等于零当empty等于n的时候 如果按341这样的顺序执行 是不是也会发生死锁

所以在这个地方 我们要强调的是实现互斥的这个p操作

一定要在实现同步的p操作之后 他们的顺序是不能颠倒的 如果颠倒的话 那么就有可能出现我们这所提到的死锁的问题

所以这是大家需要特别特别注意的地方 那接下来我们再思考一下 如果V操作的这个顺序颠倒的话 会不会出现问题呢

其实是不会的 因为V操作并不会导致任何一个进程阻塞 所以他们俩的顺序颠倒并不会发生这种循环等待的问题 所以两个V操作的顺序是可以交换的

那最后我们再来考虑一个问题 生产者生产一个产品和消费者使用一个产品 是否可以放到pv操作之间呢

其实逻辑上看是可以放到p v操作这里边的 但是如果我们把这两部分的处理都放到p v操作里边的话

那么就会导致临界区代码变得更长 也就是说 一个进程对临界区上锁的时间会增长
那这样的话 肯定不利于各个进程交替的来使用这个临界区资源

所以我们要让临界区的代码尽可能的短 因此逻辑上来看 把这两个部分放进去是没有问题的

但是实际上会对系统的效能产生影响 因此并不建议把这两个部分的操作放到p为操作里面

好的 那么这个小节当中 我们介绍了一个很经典的进程的同步互斥问题 就是生产者消费者模型

那我们根据这个问题 给出了做pv操作相关题目的一个解题思路 这个解题思路我们会在之后的

那些问题讲解当中在继续应用那生产者 消费者问题 它是一个互斥和同步的综合问题 既包含了互斥又包含了同步

但是对于我们初学者来说 比较困难的是 要发现这个题目当中隐含的两对同步关系

有时候是生产者进程在等待消费者进程 有的时候又是消费者进程需要等待生产者进程

所以这是这个题目当中的难点 它是两对不同的 一前一后的这种关系

所以我们相应的也需要给他们设置两对不同的信号量 但是对这些信号量的操作肯定都是遵循一个前V后P的 这个

原则那根据上个小节的讲解 相信这个地方已经不难理解了 另外还需要再强调一遍的是

知识回顾

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

实现互斥和实现同步是两个不同的p操作而实现互斥的

那个p操作一定要在实现同步的p操作之后 否则会导致死锁的问题

这个大家在暂停回忆一下 那么在接下来的讲解当中 我们会适当的加快一点点速度 我们不会在像之前一样每个同步信号量都来分析他背后的含义 这个需要大家自己去练习和体会

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

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

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

相关文章

基于GAN-CNN-CNN的鲁棒笔迹识别方法(三)

上一篇文章提出了一个用于笔迹识别(鉴别)的三段式模型,同时也提出了一个新数据集HTID_1,本文主要针对模型的最后一部分--笔迹识别,在HTID_1上进行实验. 数据集 实验前先介绍一下HTID_1. HTID_1是用于笔迹识别的数据集,是基于本文提出的模型制作而成的.将互联网上收集的740人笔…

Unity Shader 滚动进度条效果

Unity Shader 滚动进度条效果 前言项目场景布置导入图片修改场景设置修改图片尺寸即可调整进度 ASE连线 前言 UI要实现一个滚动进度,于是使用Shader制作一个。 项目 场景布置 导入图片 修改一下导入图片的格式,这样才能循环起来 WrapMode改为Repea…

2024/2/1学习记录

echarts 为柱条添加背景色: 若想设置折线图的点的样式,设置 series.itemStyle 指定填充颜色就好了,设置线的样式设置 lineStyle 就好了。 在折线图中倘若要设置空数据,用 - 表示即可,这对于其他系列的数据也是 适用的…

Windows11 用 HyperV 安装 Ubuntu-16.04 虚拟机

Windows11 用 HyperV 安装 Ubuntu-16.04 虚拟机 1. 确保已经开启HyperV2. 准备Ubuntu16.04镜像(推荐64位的)3. HyperV ->快速创建 -> 更改安装源 选刚刚下载的镜像(.iso)文件就好 -> 创建虚拟机[^1] 前提:VMw…

(硬核中的硬核)链路追踪落地过程中的挑战与解决方案

🎬作者简介:大家好,我是蓝胖子🥇 ☁️博客首页:CSDN主页蓝胖子的编程梦 🌄每日一句:编程中我们会遇到多少挫折?表放弃,沙漠尽头必是绿洲。 大家好,我是蓝胖子…

【Qt加密播放器】登录窗口功能补充

输入框小设计 目的:实现鼠标点击输入框时的聚焦效果。 首先在LoginForm构造函数中为账号和密码输入框添加事件过滤器。关于事件过滤器的具体介绍可以参考这篇博文:Qt消息机制和事件 ui->nameEdit->installEventFilter(this); ui->pwdEdit->…

uniapp+微信小程序+nodejs问题记录

一、前言 通过uniapp进行微信小程序调试。服务端使用NodeJs。 二、报错统计 1、本地调试时微信小程序报错:request:Cannot send network request to localhost 解决方法: 【微信小程序开发平台】-【本地设置】-勾选“不校验合法域名、web-view、TLS版本…

Python完善APC netbotz 250报告功能实现主动式运维。

首先介绍一下APC netbotz 250, 这是施耐德推出的一款机架式监控主机,能够对所有IT环境进行经济有效而且灵活的监控,号称APC史上性价比最高的环境监测方案,这可不是我吹的,是APC官网的介绍,可参考下面的官网截图。 我们…

Visual Studio 2022编译错误 Error MSB8041-此项目需要MFC库解决方案

Visual Studio 2022编译错误 Error MSB8041-此项目需要MFC库 错误原因: Visual Studio 2022安装的MFC库不够。 解决方案: 安装Visual Studio 2022 需要的MFC 库就可以了。 安装方法: 第一步,打开vs2022 工具 ->获取工具和功…

数据可视化Tableau

目录 一.第一次实验课内容 1、熟悉Tableau Desktop的工作环境。 2、熟悉数据导入、维度和度量的区分以及不同数据字段类型的标识符。 3、熟悉工作表的基本操作,主要包括行列功能区,标记卡,筛选器,智能推荐的使用。 4、作业--…

两个链表的第一个重合节点

法一:蛮力法 即顺序遍历第一个链表的每个节点,每遍历到一个节点,就在第二个链表中顺序遍历每个节点,比较是否有节点相同。该方法的时间复杂度是O(mn),空间复杂度是O(1)。…

Java进击框架:Spring-综合(十)

Java进击框架:Spring-综合(十) 前言Rest ClientsWebClientRestTemplateHTTP接口 JMS (Java消息服务)使用Spring JMS发送消息接收消息注释驱动的侦听器端点 JMXEmail任务执行和调度Spring TaskExecutor 抽象Spring TaskScheduler 抽象支持调度…

cuda基础教程(一)

文章目录 0. CURA Runtime API1. CUDA人工智能编程1.1. CUDA介绍1.2. 课程内容 2. 异构计算和并行计算2.1. 什么是并行计算2.2. 什么是异构计算 3. CUDA介绍3.1. GPU的性能指标3.2. 什么是CUDA3.3. 如何学习CUDA 4. 系统GPU查询5. Linux系统6. CUDA安装7. 查询GPU信息8. CUDA编…

[C#][opencvsharp]winform实现自定义卷积核锐化和USM锐化

【锐化介绍】 图像锐化(image sharpening)是补偿图像的轮廓,增强图像的边缘及灰度跳变的部分,使图像变得清晰,分为空间域处理和频域处理两类。图像锐化是为了突出图像上地物的边缘、轮廓,或某些线性目标要素的特征。这种滤波方法…

Python机器学习:一文讲透机器学习中的验证集法

验证集法又被称为“留出法”,基本思路是将样本数据集划分为两个互斥的集合:训练集和测试集。其中训练集占比一般为2/3~4/5,常用70%;测试集占比一般为1/5~1/3,常用30%。训练集用来构建机器学习模型;测试集也…

vit细粒度图像分类(八)SIM-Trans学习笔记

1.摘要 细粒度视觉分类(FGVC)旨在从相似的从属类别中识别物体,这对人类准确的自动识别需求具有挑战性和实用性。大多数FGVC方法侧重于判别区域挖掘的注意机制研究,而忽略了它们之间的相互依赖关系和组成的整体对象结构,而这些对模型的判别信…

11. UE5 RPG使用GameplayEffect修改角色属性(二)

上一篇写了一下GameplayEffect的基础操作,这一篇进阶一下,讲解一下GameplayEffect堆叠功能,以及能够基于这个堆叠能够实现一些怎样的效果。 经过几天的查看,发现新版的更新的真不错,而且最上面竟然直接显示编译的错误…

Django部署到服务器后无法获取到静态元素 The requested resource was not found on this server

问题描述 写了一个Django项目,部署到云主机后,访问发现图片无法访问,报错The requested resource was not found on this server 图片是一个词云图,根据爬虫爬取的信息生成的,根据爬取的信息会改变,所以没…

大数据信用报告应该去哪里查询比较好呢?

对于个人而言,大数据信用报告也变得越来越重要。那么,大数据信用报告应该去哪里查询呢?本文将为您详细介绍征信和大数据的区别,并推荐一个可靠的大数据平台。 首先,我们需要了解征信和大数据的区别 征信报告 依法采集、整理、保存…

Redis主从集群

一.资源分布 操作系统:Centos 7 Redis版本:6.2.14 IP端口角色192.168.157.1306379master192.168.157.1316379slave1192.168.157.1326379slave2 二.流程 1.创建三台虚拟机IP及端口如上且安装好Reids 2.修改三个redis.conf配置文件 其它说明&#xff1a…