2.3_9 读者-写者问题

2.3_9 读者-写者问题

(一)问题描述

  有读者和写者两组并发进程,共享一个文件,当两个或两个以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。

  因此要求:

  1.允许多个读者可以同时对文件执行读操作;

  2.只允许一个写者往文件中写信息;

  3.任一写者在完成写操作之前不允许其他读者或写者工作;

  4.写者执行写操作前,应让已有的读者和写者全部退出。


image-20240307113059194

  一个文件,可能多有多个读进程想对它进行读操作。由于读操作并不会更改这个文件当中的数据,所以,多个读进程同时读取文件是可以被允许的。

  注意:读进程和消费者是不一样的。消费者在消费的时候会把这一块数据取走,而读者进程在读数据后并不会将数据拿走,也不会更改数据。

  当一个写进程正在对文件进行写操作的时候,其他进程是不能访问这个文件的。或者换一个角度来讲,当一个写进程想要写这个共享文件的时候,它必须等待其他进程对这个文件的操作结束后,它才能往里面开始写数据。

问题1:读进程与写进程同时共享数据,可能导致读出的数据不一致的问题。

  比如此时文件中有4条数据,而读者和写者并发运行的话。当读者读取前三条数据之后,转到写者进程运行,此时写者进程写数据,并把第四条数据做了更改。之后,再切换到读者进程继续读取数据,那么此时读进程读出的第四条数据就不是它原本想要的那个数据了。

问题2:两个写进程同时共享数据,可能导致数据错误覆盖的问题。

  比如此时文件中有3条数据,而两个写者进程并发运行的话。写者1起初会认为第4块空间是空闲的,于是就会往那里写数据,正准备开始写、但还没有写的时候,切换了进程,切换到写者2,那么写者2也会认为第4块空间可以写数据。由于这两个写者数据都以为这个位置是空的,所以写者1会往这个位置写入自己的数据,写者2同时也会把自己的数据写进入。因此,就会发生,后面的写者把前面的写者所写数据给覆盖掉的问题。

(二)问题分析

  接下来要做的事情,就是尝试用PV操作来解决这个问题。

  1.关系分析。找出题目中描述的各个进程,分析它们之间的同步、互斥关系。

1)两类进程:写进程、读进程。

2)互斥关系:写进程-写进程互斥、写进程-读进程互斥。而读进程-读进程不存在互斥问题。

(三)如何实现

  我们设置一个叫rw的互斥信号量,用于实现各个进程对文件的互斥访问。

  写者进程要做的事情就是不断地写文件;读者进程要做的事情就是不断地读文件。

  由于写者、读者进程之间,要互斥地进行访问文件这个共享资源,所以写者在写文件之前需要对rw这个互斥信号量进行P操作,也就是“加锁”;写完文件之后再“解锁”,即进行V操作。读者进程同理,需要在读之前加锁、在读之后解锁。——由此实现读者和写者之间互斥地访问文件。

  但如果我们只是这样处理,会出现一个问题——不同的读者进程之间也要互斥地访问文件,即读者和读者不能同时访问文件。

  为了解决这一问题,我们可以设置一个变量count,这个变量记录了“当前有几个读进程”正在访问这个文件。count的初始值为0,也即意味着刚开始并没有读进程在访问这个文件。

  那么,当一个读进程要对文件进行加锁动作之前,它需要进行一个“检查”——看一下自己是不是第一个想要读这个文件的进程。如果自己是第一个读进程的话,那么它就会执行P(rw)操作,对文件执行加锁,同时执行count++,表示此时正在访问文件的进程数加1。而当任何一个读进程读完文件之后,都会执行count--,表示对这个文件进行访问的读进程数减1。同时,再对count的值进行判断,如果一个读进程执行完count--之后,发现count==0,那么就说明此时已经没有别的读进程正在读这个文件了,这种情况下,就说明,我这个读进程是最后一个正在读这个文件的进程,那么当我读完这个文件之后,我需要把这个文件“解锁”,即执行V(rw)

  这样一来,就可以实现读进程-读进程之间可以同时访问这个文件,同时,也不影响读进程-写进程的互斥问题。

image-20240307122619915


  到此,似乎问题已经解决了,但是仔细思考一下,还是存在一定的问题。

  思考:若两个读进程并发执行,则count=0时两个进程也许都能满足if(count==0)的条件,都会执行P(rw),从而会使第二个读进程阻塞。

  如何解决:首先思考该问题出现的原因在于什么。出现该问题的原因在于,对count变量的检查和赋值无法一气呵成。因此,解决方案就有了——设置另外一个互斥信号量来保证各读进程对count的访问是互斥的。同一时刻只能有一个读进程进行对count变量的检查和赋值操作,那么就不会出现上述问题。

image-20240307124545565


  至此,已经没什么大的问题了。但是,仔细分析一下,依然存在一个潜在的问题。

  问题:只要有读进程还在读,写进程就要一直阻塞等待,可能“饿死”。在这种算法中,读进程是优先的。(读进程是有更高优先权的)

  分析一下确实如此。由于在这个算法中,只有当最后一个读进程离开时,才会执行V(rw)对文件进行“解锁”。那么,如果在此期间有源源不断的读进程一直到来的话,也就是说这个文件一直有读进程正在读,那么写进程就会一直阻塞在P(rw)处,永远写不进来,导致写进程饿死的现象。

  如何解决:我们可以再设置一个互斥信号量w,这个信号量是用于实现“写优先”的。然后,我们可以在如图所示的位置,对w执行P、V操作。

image-20240307125148807

  自行分析一下并发执行的情况:

  读者1 —> 读者2;

  写者1 —> 写者2;

  写者1 —> 读者1;

  读者1 —> 写者1 —> 读者2。

  写者1 —> 读者1 —> 写者2。

  理解:相当于在“读者源源不断地读文件”之间,给了写者一个参加排队的机会。写者只要发起P(w)并阻塞了,写者就会被放进阻塞队列。当读进程V(w)之后就会轮到写者开始写。而不是读者进程源源不断地读、完全不考虑写进程是否要写。(因为“记录型信号量”,它除了“记录当前这种资源还有几个”之外,它还有一个排队功能)

  结论:在这种算法中,连续进入的多个读者可以同时读文件;写者和其他进程不能同时访问文件;写者不会饥饿,单页并不是真正的“写优先”,而是相对公平的先来先服务原则。——因此,有的书上把这种算法称为“读写公平法”。

  如何实现“真正的写优先”,可自行上网查阅。

总结

读者-写者问题

  读者-写者问题为我们解决复杂的互斥问题提供了一个参考思路。

  复杂之处在于:读者-读者不互斥,而读者-写者互斥,写者-写者互斥。

  其核心思想在于设置了一个计数器count用来记录当前正在访问共享文件的读进程数。我们可以用count的值来判断当前进入的进程是否是第一个/最后一个读进程,从而做出不同的处理。(是第一个来读的,则加锁;是最后一个不读的,则解锁)

  另外,对count变量的检查和赋值不能一气呵成导致了一些错误,如果需要实现“一气呵成”,自然应该想到用互斥信号量

  注意:这种“一气呵成”不要理解为,在此期间就不会发生进程切换了。进程切换依然是会发生的,只是说A做到一半,切换成B时,B并不能再处理了,只有换回A让A继续做完才能结束,这样的“一气呵成”。

  最后,还要认真体会我们是如何解决“写进程饥饿”问题的。(即上面的信号量w


注意

  我们并不是学习记忆这几个问题本身,而是通过对这些互斥、同步问题的解决思路进行吸取借鉴。绝大多数的考研PV操作大题都可以用之前介绍的几种生产者-消费者问题的思想来解决,如果遇到更复杂的问题,可以想想能否用读者-写者问题的这几个思想来解决。

  问题本身并不重要,解决问题的分析过程、解决思路才是重要的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【nvm】nvm的安装和使用

简言 nvm(nvm-windows)的安装和使用。 nvm 允许你通过命令行快速安装和使用不同版本的 node。 nvm 适用于任何符合 POSIX 标准的 shell(sh、dash、ksh、zsh、bash),尤其适用于以下平台:Unix、macOS 和 windows WSL。 不过 nvm 在…

安全防御第七次作业

拓扑图如图所示: 问题:在FW7和FW8之间建立一条IPSEC通道保证10.0.2.0/24网段 可以正常访问到192.168.1.0/24 注:基础配置我在此省略了 一、NAT配置 FW4: FW6: 二、在FW4上做服务器映射 三、配置IPSEC FW5&#xff…

用xshell7连接服务器,读取后台日志

有时候前端需要读取一些后台日志,比如,有时候接一些验证码啥的 或者有时候前后端不分离时,前端上线项目 先讲一下怎么用密码方式连接服务器 密码方式连接服务器 第一步,安装xshell,在新建会话中填写主机&#xff0…

两两交换链表中的节点+力扣

题目 题目链接 . - 力扣(LeetCode) 题目描述 代码实现 class Solution { public:ListNode* swapPairs(ListNode* head) {if(head nullptr || head->next nullptr) return head;ListNode *tmpHead swapPairs(head->next->next);ListNode …

企微hook源码

企微hook源码已经在QQ群内开源。速度进群下载,避免和谐。 QQ群:649480745

AI应用开发-python对MySQL数据的常见使用

AI应用开发相关目录 本专栏包括AI应用开发相关内容分享,包括不限于AI算法部署实施细节、AI应用后端分析服务相关概念及开发技巧、AI应用后端应用服务相关概念及开发技巧、AI应用前端实现路径及开发技巧 适用于具备一定算法及Python使用基础的人群 AI应用开发流程概…

如何做代币分析:以 ARB 币为例

作者:lesleyfootprint.network 编译:mingfootprint.network 数据源:ARB 代币仪表板 (仅包括以太坊数据) 在加密货币和数字资产领域,代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关的数据…

GitHub Pages部署静态页面

GitHub Pages是GitHub提供的静态页面托管服务,可以用来托管个人博客、项目文档等静态页面。GitHub Pages支持Jekyll,可以使用Jekyll构建博客,也可以使用其他静态页面生成器。现在GitHub Pages也在公测通过工作流部署静态页面,可以…

【趣玩一下】StreamDiffusion一秒100张!实时生成二次元老婆照!

源代码 https://github.com/cumulo-autumn/StreamDiffusion 基础原理 首先Stream Batch,是将原来顺序的去噪步骤改为批量化处理。允许在一个批处理中,每幅图像处于去噪流程的不同阶段。 如此一来,可以大大减少UNet推理次数,显著…

【SQL】1321. 餐馆营业额变化增长(窗口函数rows between 、range between;DATEDIFF()函数)

前述 窗口函数相关知识推荐阅读: 通俗易懂的学会:SQL窗口函数 窗口函数rows between 、range between的使用 MySQL中的DATEDIFF()函数 mysql data类型的加减 常用函数: ROUND() 函数:用于将数值四舍五入到指定的小数位数。FLOO…

Python爬虫——scrapy-2

目录 scrapy简介 安装ipython 基本使用 访问百度 总结 scrapy简介 scrapy shell是Scrapy框架提供的一个交互式命令行工具,用于快速调试和测试Scrapy爬虫。它能够加载Scrapy项目的设置和爬虫代码,并提供一个交互式环境,可以在其中执行Scra…

云计算项目七:jump-server安装部署

jump-server安装部署 配置清单 jumpserver概述 Jumpserver是一款开源的堡垒机,可使系统的管理员和开发人员安全的连接到企业内部服务器上执行操作,并且支持大部分操作系统,是一款非常安全的远程连接工具 常见支持的系统 CentOS, RedHat, …

GNURadio+USRP+OFDM实现文件传输

文章目录 前言一、发送端1、参数配置1)Random Source2)stream to Tagged stream3)Stream CRC324)Protocol Formatter5)Repack Bits6)Virtual Sink7)Chunks to Symbols8)Tagged Strea…

关于装载类子系统

装载类子系统 类加载器字节码调节器类加载运行时数据区 类加载器 将class文件加载进jvm的方法去,并在方法去中创建一个java.lang.Class对象作为外界访问这个类的接口。实现这个动作的代码模块称为类加载器。 类加载器分类 启动类加载器(Bootstrap C…

keycloak18.0.0==本地源码启动

github下载源码, 版本18.0.0 java和maven的版本如下 E:\keycloak-18.0.0>java -version java version "21.0.1" 2023-10-17 LTS Java(TM) SE Runtime Environment (build 21.0.112-LTS-29) Java HotSpot(TM) 64-Bit Server VM (build 21.0.112-LTS-…

EMC测试整改:提升产品合规性和市场竞争力?|深圳比创达电子

在当前的产品研发和制造领域,电磁兼容(EMC)测试是确保产品符合法规要求并能够在各种电磁环境下正常工作的重要环节。然而,很多企业在进行EMC测试时可能会遇到一些问题和不合格情况,因此需要进行整改来提升产品的合规性…

leetcode 热题 100_合并区间

题解一: 排序:先将区间按左边界从小到大进行排序,假设排序后a区间在b区间之前,根据a区间右边界和b区间左边界的大小判断是否重叠,如果重叠则将区间合并为一个。考虑到区间完全处于另一区间内的情况,合并时应…

一个数据库表格缺少自动增加的字段导致添加一条数据失败

一个数据库表格缺少自动增加的字段导致添加一条数据失败。最近要整理出一个cms网站源程序,因此新建了一个目录,将需要的文件复制到该目录。复制好以后,试用的时候发现添加留言失败。经过数小时的查找原因,最后找到原因&#xff0c…

JVM-类加载机制

名词解释 *.class文件的结构 查看指令: javap -verbose hello.class 包含信息: 结构信息(版本号,大小信息); 元数据(类,继承,接口,字段声明,方法声…