读者-写者问题 (操作系统-进程)

2023-11-17

问题描述:有读者和写者两组并发进程,共享一个文件,当两个或两个以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:
允许多个读者可以同时对文件执行读操作
只允许一个写者往文件中写信息
任一写者在完成写操作之前不允许其他读者或写者工作
写者执行写操作前,应让已有的读者和写者全部退出
读者写者问题问题分析
两类进程:写进程、读进程
互斥关系:写进程—写进程、写进程—读进程。读进程与读进程不存在互斥问题。

读进程优先算法

/***********信号量定义*************/
semaphore rw=1; //用于实现对共享文件的互斥访问
int count = 0; //记录当前有几个读进程在访问文件
semaphore mutex = 1;//用于保证对count变量的互斥访问
/**********************************/

/**********写者进程*************/
writer (){
	while(1){
		P(rw); //写之前“加锁”
		写文件操作…
		V(rw); //写完了“解锁”
	}
}
/**********************************/

/***************读者进程**************/
reader (){
	while(1){
		P(mutex); //各读进程互斥访问count
		if(count==0) //由第一个读进程负责
			P(rw); //读之前“加锁”
		count++; //访问文件的读进程数+1
		V(mutex);
		读文件…
		P(mutex); //各读进程互斥访问count
		count--; //访问文件的读进程数-1
		if(count==0) //由最后一个读进程负责
			V(rw); //读完了“解锁”
		V(mutex);
	}
}
/********************************/

以上就是读进程的优先的代码演示。
问题一:为啥要设置metex这个互斥信号量呢?我们先假设一下没用这个信号量时的情况。代码如下:

reader (){
	while(1){
		if(count==0) //由第一个读进程负责
			P(rw); //读之前“加锁”
		count++; //访问文件的读进程数+1
		读文件…
		count--; //访问文件的读进程数-1
		if(count==0) //由最后一个读进程负责
			V(rw); //读完了“解锁”
	}
}

我们假设这个时候两个写者进程同时进入。都执行了第三行代码if(count==0)判断到count为0,都进入P(rw)的加锁操作。此时必然有一个进程阻塞在此。所以加上metex这个互斥信号量来保证各读进程互斥访问count。那么有人问了我用count++来让对count的操作都在一条代码中是否可行。

// An highlighted block
if(count++ == 0) //count++和判断同时执行
	P(rw); //读之前“加锁”
//count++; //已合并到第一行代码中

这样做当然是不可行的,因为 count++不属于原子操作,它的执行过程为1、读内存到寄存器i2、在寄存器中自增;3、写回内存。所以只能通过加锁来实现。
问题二:当源源不断的有读者进程进入时,就永远执行到不最后一个读进程解锁的代码,此时写进程就只能一直在等待这就造成了“饥饿”的现象。所以这种写法被称为读者优先。为了解决这个问题我们又引出了写者优先的解决算法。

写者优先算法

/***********信号量定义*************/
semaphore rw=1; //用于实现对共享文件的互斥访问
int count = 0; //记录当前有几个读进程在访问文件
semaphore mutex = 1;//用于保证对count变量的互斥访问
semaphore w=1; //用于实现写优先
/**********************************/

/**********写者进程*************/
writer (){
	while(1){
		P(w);
		P(rw);
		写文件…
		V(rw);
		V(w);
	}
}
/**********************************/

/***************读者进程**************/
reader (){
	while(1){
		P(w);
		P(mutex); //各读进程互斥访问count
		if(count==0) //由第一个读进程负责
			P(rw); //读之前“加锁”
		count++; //访问文件的读进程数+1
		V(mutex);
		V(w);
		读文件…
		P(mutex); //各读进程互斥访问count
		count--; //访问文件的读进程数-1
		if(count==0) //由最后一个读进程负责
			V(rw); //读完了“解锁”
		V(mutex);
	}
}
/********************************/

在写优先算法中,哪怕有源源不断的读进程进入时都不会饿死写进程。因为当未v(w)时都会在p(w)中被挂起,而当v(w)时谁先进入的挂起队列谁优先。这属于先来先服务原则,又叫读写公平法。

参考于2019 王道考研 操作系统课程。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

读者-写者问题 (操作系统-进程) 的相关文章

  • C Primer Plus 第六章编程练习

    第六章 编程练习 6 1 题 目 编写一个程序 创建一个包含26个元素的数组 并在其中储存26个 小写字母 然后打印数组的所有内容 完成时间 2020 2 3 作 者 林夕

随机推荐

  • 【项目实战】大文件断点续传,搞起

    今天给大家分享的又是一篇实战文章 也是最近私活里遇到的 万能的互联网给了我办法 分享一下 背景 最近接到一个新的需求 需要上传2G左右的视频文件 用测试环境的OSS试了一下 上传需要十几分钟 再考虑到公司的资源问题 果断放弃该方案 一提到大
  • MJRefresh原理分析

    MJRefresh是流行的下拉刷新控件 前段时间为了修复一个BUG 读了它的源码 本文总结一下实现的原理 下拉刷新的基本原理 大部分的下拉刷新控件 都是用contentInset实现的 默认情况下 如果一个UIScrollView的左上角在
  • CNN进行非接触掌纹识别的改进过程

    1 模型和参数不变 模型 2个卷积层 1个全连接层 参数 BATCH SIZE 32 定义超参数 每次处理32张图片 EPOCHS 20 将数据集训练20轮 LR 0 01 学习率 TRAIN DIVISION 3 训练集划分占比 opti
  • 小程序上线流程

    1 配置服务器域名 小程序接口API 2 业务域名配置 首先配置小程序的业务域名 将下载txt文件放在A 域名根目录下 然后才可以配置业务域名为 A 主要应用场景为 小程序页面跳转其他小程序 3 npm run build weapp 编译
  • 【数据库复习】第二章关系数据库

    目录 一 关系数据结构及形式化定义 1 1关系 1 2关系模式 1 3关系数据库 1 4关系模型的存储结构 二 关系操作 三 关系的完整性 四 关系代数 4 1传统的集合运算 4 2专门的关系运算 4 2 1选择 selection 4 2
  • const int & a = 1;

    int a 1 报错 引用需要一个合法的内存空间 const int a 1 正确 类似于int temp 1 const int a temp
  • String时间类型转换为ZonedDateTime时间类型

    搞了一个早上 不知道怎么弄这个东西 最后发现没有必要将ZonedDateTime写的很全 可以精简的封装 public static ZonedDateTime changeShanghaiToUTC String beijingDateT
  • 【MIUI9】小米平板1MIPAD1欧版ROM历史ROM下载地址-另附挥泪典藏版V9系统

    费劲整理来的 上边是 小米平板1 MIPAD1的 ROM 下边是MI3W小米3联通版的ROM 欧版xiaomi eu系统的好处就是省电 miui MIPAD V9 2 4 0 KXFCNEK 97354839c6 4 4 zip 这个是小米
  • com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message

    报错 com mongodb MongoSocketReadTimeoutException Timeout while receiving message at com mongodb connection InternalStreamC
  • C++ list容器详解

    C list容器 list容器的基本概念 1 list的构造函数 2 list的赋值和交换 3 list的大小操作 4 list的插入和删除 5 list的数据存取 6 list的反转与排序 7 list的排序案例 list容器的基本概念
  • Vue 源码解读(12)—— patch

    当学习成为了习惯 知识也就变成了常识 感谢各位的 关注 点赞 收藏和评论 新视频和文章会第一时间在微信公众号发送 欢迎关注 李永宁lyn 文章已收录到 github 仓库 liyongning blog 欢迎 Watch 和 Star 前言
  • linux系统提示只读文件系统,无法创建文件

    可能磁盘写保护 第一步 df h 确定文件夹对应的磁盘 第二步 mount ro为只读 rw为可读可写 可以用mount命令看看ro的分区 如果发现有ro 就重新mount 如 umount dev sda1 mount dev sda1
  • 备战2022,Android中高级面试必知必会

    在过去不久的金九银十 有些小伙伴已经找到了理想的工作 当然也有很多小伙伴因为准备不充分 面试挂了 临近年关 最近有很多网友都在求大厂面试题 正好我在9月份和10月份整理和收集了 Android 中高级面试真题解析 于是就发上来分享给大家 这
  • 如何使用matlab读取excel中的表格数据

    如何使用matlab读取excel中的表格数据 设备系统 win10 操作软件 matlab2020b 1 首先打开matlab软件 点击 新建 脚本 2 在脚本中输入代码 A xlsread C Users Administrator D
  • [附源码]java毕业设计订单管理系统

    项目运行 环境配置 Jdk1 8 Tomcat7 0 Mysql HBuilderX Webstorm也行 Eclispe IntelliJ IDEA Eclispe MyEclispe Sts都支持 项目技术 SSM mybatis Ma
  • 【操作系统】虚拟内存的最大容量和实际容量的区别(以一道例题开头)

    实际内存为什么是2GB 512MB 因为实际容量是取CPU寻址 2 32B 与内存与外存之和 2GB 512MB 的最小值 就是相当于 数学里面两个值取最小值一样
  • gdbserver配置、远程调试以及ssh配置

    引言 GDB调试主要有两种方法 1 直接在目标板上通过gdb调试程序 2 在目标板上通过gdbserver运行程序 在宿主机上通过gdb调试程序 本篇文章主要来说明一下gdbserver远程调试的方法 主要以VScode举例说明 步骤 一
  • idea下载Scala插件(详细)

    目录 1 idea下载Scala 2 点击 Restart IDE 重启IDEA即可 3 创建scala目录 4 Mark scala目录为 source root 5 在windows的电脑安装scala jdk并且配置 环境变量 6 在
  • labelImg支持中文标注的文件

    链接 https pan baidu com s 1XCuLTlKRN7gVxJdQkcKnUw 密码 iaws
  • 读者-写者问题 (操作系统-进程)

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