当前位置: 首页 > news >正文

操作系统——读者写者问题

读者写者问题

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

因此要求:

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

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

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

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

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

    同步关系:个人感觉这个问题上并没有很强的同步关系。并不是说读完了,就一定要通知写进程写入数据。写完了,就一定要通知读进程读取数据。

    互斥关系:读进程和写进程不能同时访问文件。写进程和写进程之间也存在互斥关系。但是读进程和读进程不存在互斥关系。

  2. 整理思路并设置信号量。设置需要的信号量,并根据题目中条件确定信号量初值。(互斥信号量初值一般为1)

    文件在这里可以作为一个互斥资源(file,初始值为1),需要注意的是读进程和读进程之间并不存在互斥关系,所以我们需要想办法避免读进程和读进程之间去重复对文件加锁(这里加锁就指的是对信号量进行P操作)的过程。

    写进程在操作之前先尝试能不能加锁成功,不能则阻塞;能则进行操作,操作完成后将资源进行释放。

    读进程就稍稍麻烦一些,大概分为以下步骤:

    • 首先需要维护一个当前正在读取文件的进程计数器。
    • 在读进程读取文件之前先判断计数器是不是为0。
      • 如果为0的话,就证明当前没有任何读进程在读取文件。所以此时需要尝试获取锁,如果不能获取到则证明有写进程在写文件,那么当前进程只能阻塞。如果能获取到锁,就可以读取文件,在真正I/O操作之前需要将计数器加1。
      • 如果不是为0的话,就证明当前还有读进程在读取文件,此时读进程一定是占有锁的,那么当前进程就不用再去获取锁了,可以直接读取文件,同样在读文件之前需要将计数器加1。
    • 在读取文件之后需要判断计数器是不是为1。
      • 如果为不为1的话,则证明还有进程在读取文件,此时锁肯定是不能释放的。计数器需要减1。
      • 如果为1,则证明当前没有进程在读取文件,此时需要释放锁,然后将计数器减1.

按照以上思路,可以简单的先实现一下代码,至于有什么其他问题,实现后再进行分析。

信号量

semapore file = 1;
int i = 0;//读者数量

写进程

void writer(){P(file);写入数据到文件;V(file);
}

读进程

void reader(){if(i == 0){P(file);}i++;从文件中读取数据;i--;if(i == 0){V(file);}}
}

仔细分析一下,读进程的代码存在并发问题,就是在if(i == 0)的地方,如果有n个进程同时进入此判断,那么,必定会有n-1个进程会进入阻塞状态。所以各个读进程对计数器的判断也是属于互斥关系,那么就需要设置一个互斥信号量解决这个互斥问题。

信号量

semapore file = 1; // 解决文件互斥问题的信号量
int i = 0;//读者数量
semapore mutex = 1; // 解决读者数量互斥问题的信号量

写进程

void writer(){P(file);写入数据到文件;V(file);
}

读进程

void reader(){P(mutex);if(i == 0){P(file);}i++;V(mutex);从文件中读取数据;P(mutex);i--;if(i == 0){V(file);}V(mutex);}
}

这样一看,确实是解决了读进程的并发问题,但是如果一直有读进程在读数据的话,写进程就会一直被阻塞,直到饿死。所以还得再想一个方案。

仔细想想,出现读进程一直占用资源的问题无非就是,读写进程对信号量file的上锁的整个过程并不是互斥的,所以再增加一个锁对这个过程进行上锁就可以了。

信号量

semapore file = 1; // 解决文件互斥问题的信号量
int i = 0;//读者数量
semapore mutex = 1; // 解决读者数量互斥问题的信号量
semapore fair = 1;

写进程

void writer(){P(fair);P(file);V(fair);写入数据到文件;V(file);
}

读进程

void reader(){P(fair);P(mutex);if(i == 0){P(file);}i++;V(mutex);V(fair);从文件中读取数据;P(mutex);i--;if(i == 0){V(file);}V(mutex);}
}

http://www.dtcms.com/a/313432.html

相关文章:

  • KNX协议介绍
  • Nvidia Orin + RealSense D435i 与3D地图实现导航
  • Ubuntu系统VScode实现opencv(c++)视频的处理与保存
  • [硬件电路-129]:模拟电路 - 继电器的工作原理、关键指标、常用芯片与管脚定义
  • SpringAI的使用
  • Socket编程——TCP协议
  • 从一到无穷大 #51:突破阿姆达尔定律:COZ因果剖析与串行优化八法
  • Java学习第一百零一部分——网关(Gateway)
  • java测试题(ssm框架)
  • 02.Redis 安装
  • MPLS 静态LSP
  • TV电视版软件集合分享
  • 深入理解Java并发编程:原理、实战与最佳实践
  • Redis 7 中的 Set 和 Zset 使用
  • 基于transformer的目标检测——匈牙利匹配算法
  • 深入解析HashMap:原理与性能优化
  • Vim编辑器详解:从入门到高效使用
  • 从零开始的CAD|CAE开发: LBM源码实现分享
  • 编程语言分类
  • JAVAEE--5.多线程之常见的锁策略
  • AI Competitor Intelligence Agent Team
  • 【openlayers框架学习】七:绘制线要素以及点击画线功能
  • 力扣热题100----------141.环形链表
  • 基于BiLSTM+CRF实现NER
  • 【机器人】VLN-R1 微调 | 增强训练 | 连续导航
  • Web3合约ABI,合约地址生成部署调用及创建,连接钱包,基础交易流程
  • ARPO:让LLM智能体更高效探索
  • 【Linux网络编程基础--socket地址API】
  • 多 4G 通讯模组共存时的干扰问题深度解析与解决方案
  • leecode-每日一题-2106. 摘水果