OS记录型信号量-读者写者问题

news/2025/2/22 2:40:40

dtitle: OS记录型信号量-读者写者问题
date: 2021-04-09 19:06:16
tags: [信号量机制, OS, 读者写者问题, 记录型信号量]
categories: OS


利用记录型信号量实现读者写者问题

写在最前

最近对 OS 这门课着了迷,hhh,拿起课本就是硬啃

用了一段时间领悟了记录型信号量的几个版本

这是对记录型信号量的一个应用,那么 pv操作( 即wait()和signal() )的具体代码描述 肯定是要烂熟于心的

在这里我就不写书上那么详细了

在这里我唠叨几句,pv操作虽然简简单单的这几行代码,但是非常具有思考性,很多细节只有自己想通了,才能将pv操作“玩弄于鼓掌之上”

改篇详细介绍一下pv操作 和 里面值得思考的细节


wait(S) {
    S->value--;
    if (S->value < 0) 
        block(S->list);
}


signal(S) {
    S->value++;
    if (S->value <= 0)
        signal(S->list);
}

初始版本

为什么叫初始版本呢? 因为它不公平,对读者友好,对写者十分不友好

我们知道读者写者问题中 读读操作是可以同时进行的,唯独写操作不可以与任何操作同时进行

可以进行的操作 单独读 多个同时读 单独写 ;同时读写 和 多个同时写 是不允许的

在这个版本中只有当所有的读者都不再占用文件的时候 写进程才有机会访问文件,光说没什么卵用

下面分析代码,细致地了解到底是怎么个情况,我会将分析对应地写到注释里

着重分析初始版本,因为后面实现读者写者公平的版本 仅仅是对它的一个改良

代码


//  readcount 表示当前有几个读进程正在读文件
int readcount = 0;
// rmutex 用于实现 读读进程 之间的互斥,保护readcount, 防止多个读进程同时访问/修改 readcount
// wmutext 用于实现 读写、写写之间的互斥,总之,一句话,用于实现某一个写进程和其它所有进程的互斥
semaphore rmutex = 1, wmutex = 1;

// 读进程
void Reader() {
    do {
        // 占用 readcount
        // 可以理解为 给readcount "上锁"
        wait(rmutex);
        /* 
        当readcount == 0时,  说明 这个文件可能正在被写进程访问 或者是这个文件在此之前一直处于闲置
        状态且写进程也无意争抢该文件,也有可能 于此同时写进程也想要访问这个文件, 两者将争夺该文件。
        因此必须加上一个wait语句来保证某一个写进程和其它任意进程的互斥。
        
        下面分析一下 当readcount == 0时, 这个进程执行wait语句之后可能的结果
        我将结果分为两个大项,四个小项 			
        - 抢到了文件(在抢的一瞬间文件空闲) 
        	①文件空闲 且执行wait语句前没有写进程和它抢,它肯定是顺利地得到了文件。
                wmutex值的变化:
                 	wmutex 在wait语句执行前的值为 1 执行之后为 0  
                之后若再有写进程想要访问文件:
                    <1>若在signal(wmutex)语句执行之前 有一个写进程再想通过wait(mutex)来获得文件,
                    那么结果只能是 wmutex 值变为 -1 ,这个写进程被阻塞 进入阻塞队列,等待所有读进程
                    都读完之后,readcount变为0 ,执行signal(wmutex)语句,才会去唤醒这个写进程
                    (在此情况下,这个写进程在阻塞队列中必定处于队头),
                    顺带着说了 这也是对写进程的不公平之处。
                    <2>若又有一个读进程想要访问文件,请看第50-51行注释
        

   	    	②文件空闲 但于此同时有一个写进程也想通过wait语句争抢文件 对文件"上锁",
       		但是它先于写进程一步抢到了。
        		wmutex值的变化 以及之后再有进程想要访问文件的变化同上述第一条
        - 没有抢到文件(在抢到之前,文件已经被写进程占了)
        	①文件不空闲 有一个写进程一直都在使用着文件。
                wmutex 在wait执行前的值为m,(m <= 0), 执行后为 m-1, 
                为什么说wmutex原来值为一个<=0的数呢?
                在这里又要分两种情况,在写进程开始写文件之后,这个读进程想要读文件之前的期间:
                    1. 没有其它进程想要访问文件,那么阻塞队列一定是空的,wmutex 值为0
                    2. 有其它的n个进程曾想要访问文件,结果肯定是它们都进入了阻塞队列,
                    wmutex值为 -n == m 
        	②文件空闲 但同时,写进程也想通过wait语句争抢文件 对文件"上锁",
        	写进程抢先一步,得到了文件。
                wmutex 在wait语句执行之前的值为 0, 之后值为 -1 
        */
        
        /*
        	当readcount != 0时, 说明现在有读进程正在读文件,并且第一个执行读操作的进程已经针对
        	写进程上了锁,因此直接令readcount++, 然后进行读操作,读完以后将readcount再减一
        */
        /*
        	以上 其实我已经把整个的思路都给讲了,并且交代了为什么会对写进程不公平
        	还有几种简单情况我没有提的就是 上来就是写进程抢到了文件,在第37行注释中所述情况
        	也是把这个情况给包括了
        */
        /*
        	像进程同步互斥、带pv操作的这种这种联系性很大的代码 
        	真的不能说我要讲就只讲这一段 它们之间紧密联系
        	单独地理解一段代码很难领略到实质,我也是讲着讲着第一段就把整个的都给说出来了hhhh
        	也算是给广大后来者提供一种学习的方式吧 要善于整体感知
        */
        
        if (readcount == 0) wait(wmutex);
        readcount++;
        // "释放" readcount的锁 
        signal(rmutex);
        ...
        perform read operation;
        ...
        wait(rmutex);
        readcount--;
        if (readcount == 0) signal(wmutex);
        signal(rmutex);
    }while(TRUE);
}

// 写进程
void Writer() {
    do {
        wait(wmutex);
        perform write operation;
        signal(wmutex);
    } while(TRUE);
}

// 程序入口
void main() {
    cobegin
        Reader();  Writer();
    coend
}



http://www.niftyadmin.cn/n/1616054.html

相关文章

Java枚举源码级理解

title: Java枚举源码级理解 date: 2020-11-08 16:47:39 tags: [Java枚举, 源码理解, Java源码理解, 枚举, JavaBase, Java基础] categories: Java Java中枚举体的一些东西很怪&#xff0c;看了源码之后恍然大悟&#xff0c;收获颇丰废话不多说&#xff0c;直接上代码 第一种形…

Java加载顺序

title: Java代码执行顺序 date: 2021-03-30 20:28:37 tags: [JavaBase, Java变量加载顺序] categories: Java Java源文件中代码的加载顺序执行顺序 对类的加载 加载类的方法和静态属性 为方法和静态属性分配空间按照静态代码块和静态属性定义语句 在源文件中的顺序执行静态代…

hadoop一键启动脚本

Hadoop一键启动脚本 #!/bin/bash jps>tmp.txt NNcat tmp.txt|grep -w NameNode DNcat tmp.txt|grep -w DataNode SNNcat tmp.txt|grep -w SecondaryNameNode RMcat tmp.txt|grep -w ResourceManager NMcat tmp.txt|grep -w NodeManager JHScat tmp.txt|grep -w JobHistoryS…

hadoop一键关闭脚本

hadoop一键关闭脚本 #!/bin/bash jps>tmp.txt NNcat tmp.txt|grep -w NameNode DNcat tmp.txt|grep -w DataNode SNNcat tmp.txt|grep -w SecondaryNameNode RMcat tmp.txt|grep -w ResourceManager NMcat tmp.txt|grep -w NodeManager JHScat tmp.txt|grep -w JobHistoryS…

算法思想之求值法

一、求值法 求值法是一种最简单的问题求解方法&#xff0c;也是最常见的算法设计方法。它是根据问题给定的条件&#xff0c;运用基本的顺序、选择和循环控制语句结构来解决问题。例如&#xff1a;求最大值、求平均值等问题就是其具体应用。 二、算法设计思路 1、确定边界约束…

C语言链表项目-学生信息管理系统

核心知识 单向链表基本操作对文件的基本操作 使用说明 请先建好一个.txt文件并记下路径名&#xff0c;文件可以为空&#xff0c;也可以预先存好数据建议创建一个空文件&#xff0c;通过程序来向文件中存数据。手动去文件中存数据需要严格按照格式。 如果想预先手动存一些数据…

Quora与Siri强强联手将威胁Google核心业务及Wiki问答宝座

随着Google的兴起&#xff0c;以及其他新兴技术产品的出现&#xff0c;新闻媒体的视线逐渐从社交问答网站Quora转移。如今&#xff0c;苹果整合了世界上最复杂的人工智能&#xff0c;若将Siri整合到Quora&#xff0c;会是怎样一番景象&#xff1f; Quora将成为一个浓缩了主观知…

苹果的工厂价值几何?

对苹果财务报表的分析让我们可以一窥苹果的战略意图&#xff0c;为更好地对其进行挖掘&#xff0c;在此引入另一个重要指标&#xff1a;“机械&#xff0c;设备和内部使用的软件”&#xff08;M&E&#xff09;&#xff0c;如下图中的黄线所示。 这让我们一眼看去就可以对这…