操作系统:读者写者问题

article/2025/9/30 8:19:23

操作系统:读者写者问题

    • 问题:
      • 一、读者-写者问题: 读者优先
      • 二、读者-写者问题:写进程优先
    • 三、读者写者问题的应用---独木桥问题
    • 类型1.一次只能过一辆车
      • 类型2.一次能过多辆车
    • 四、总结
    • 附代码:
        • //读者优先
        • //写者优先
        • //公平竞争
      • 教材原文:

在这里插入图片描述

问题:

在操作系统中,我们处理各种过程,这些过程可能会使用系统中存在的文件。基本上,我们对文件执行两个操作,即读取和写入。所有这些过程都可以执行这两个操作。但是这里出现的问题是:

  • 如果一个进程正在某个文件上写入内容,而另一个进程也同时开始在同一文件上写入内容,则系统将进入不一致状态。在特定的时间仅应允许一个进程更改文件中存在的数据的值。
  • 另一个问题是,如果一个进程正在读取文件,而另一个进程同时在同一文件上写入,则可能会导致读取不干净,因为在该文件上写入的进程会更改文件的值,但是读取该文件的过程将读取文件中存在的旧值。因此,应避免这种情况。
    在这里插入图片描述

一、读者-写者问题: 读者优先

1.问题描述
有两组并发进程:读者和写者,共享一个文件F,要求:

- 允许多个读者同时执行读操作
- 任一写者在完成写操作之前不允许其它读者或写者工作
- 写者执行写操作前,应让已有的写者和读者全部退出

2.问题分析

- 共享数据(文件、记录)由Reader和Writer是两组并发进程共享
- Reader和Writer两组并发进程
- 同组的Reader进程可同时对文件进行读,不用互斥
- 写-写互斥
- 读-写互斥

3.读者写者问题–读者优先
对于读者优先,应满足下列条件:

①如果新读者到:但有其它读者正在读,则新读者也可以读;
②有写者等待,但有其它读者正在读,则新读者也可以读;
③有写者写,新读者等待。

如果新写者到

①无读者,新写者可以写;
②有读者,新写者等待;
③有其它写者,新写者等待。
4.信号量及变量设计

  1. 对读进程计数变量:readcount=0
  2. 对计数器操作的互斥信号量:rc_mutex=1
  3. 读写互斥、写写互斥信号量:writeblock=1

5.读者优先算法设计

int readcount=0; //读进程计数器 
semaphore writeblock, rc_mutex ; 
writeblock=1; rc_mutex=1; 
main() { 
cobegin 
process reader_i( )//i=1,2,…n 
process writer_j( ) //j=1,2,…m 
coend 
}process reader_i() 
{ 
P(rc_mutex); 
readcount++; 
if(readcount==1) 
P(writeblock); 
V(rc_mutex); 
{读文件}; 
P(rc_mutex); 
readcount--; 
if(readcount==0) 
V(writeblock); 
V(rc_mutex);} process writer_j( ) 
{ 
P(writeblock); 
{写文件}; 
V(writeblock); 
}

6.问题分析
(1)读者优先,当有读者时,写者将被推迟
(2)会出现写者饥饿现像

二、读者-写者问题:写进程优先

1.信号量设置
(1)信号量x:readcount的互斥操作信号量
(2)信号量y:writecount的互斥操作信号量
(3)信号量wsem:写写互斥、读写互斥信号量
(4)信号量rsem:读者、写者竞争的信号量,读者每次都释放,最后一个写者才释放。
(5)信号量z:读者排队的信号量
2.算法设计

int readcount,writecount; 
semaphore x=1,y=1,z=1,wsem=1,rsem=1; 
void reader() 
{ 
Wait(z) ; 
Wait(rsem); 
Wait(x); 
readcount++; 
if(readcount==1) Wait(wsem); 
Signal(x); 
Signal(rsem); 
signal(z); 
readunit(); 
Wait(x); 
readcount--; 
if(readcount==0) Signal(wsem); 
Signal(x); 
}Void writer() 
{ 
{ 
Wait(y); 
writecount++; 
if(writecount==1) Wait(rsem); 
signal(y); 
wait(wsem); 
writeunit(); 
signal(wsem); 
Wait(y); 
writecount--; 
if(writecount==0) signal(rsem); 
Signal(y); 
} Void main() 
{ 
readcount=writecount=0; 
parbegin(reader,writter); 
}

三、读者写者问题的应用—独木桥问题

类型1.一次只能过一辆车

1.问题描述
东西向汽车驶过独木桥,为了保证交通安全,只要桥上无车,则允许一方的汽车过桥,待其全部过完后才允许另一方的汽车过桥,限制桥面上一次只过一辆车。请用信号量和pv操作写出汽车过独木桥问题的同步算法。
2.问题分析
(1)系统中的进程

两类:从东向西行驶的汽车;从西向东行驶的汽车

(2)进程间的关系

①同向行驶的汽车需要排队;
②对向行驶的汽车需要同步,保证不能在独木桥上相遇

3.信号量设计
(1)mutexA:用于同向(从东向西)行驶的汽车对统计信息进行修改时的互斥信用量,初值为 1
(2)mutexB:用于同向(从西向东)行驶的汽车行驶的汽车对统计信息进行修改时的互斥信用量,初值为 1
(3)bridge:两个方向的汽车过桥的时的信号量,两个方向竞争此信号量,竞争成功的一方获得过桥资格,初值为 1
(4)mutex:过桥时的互斥信号量
4.算法设计

semaphore mutexA,mutexB,bridge,mutex; 
mutexA=1,mutexB=1,bridge=1,mutex=1; 
int countA=0,countB=0; 
main() { 
cobegin 
process east-to-west-i();//i=1,2,3…n 
process west-to-east-j();//j=1,2,3…m 
coend 
}
process east-to-west-i();//i=1,2,3…n 
{ p(mutexA); 
countA++; 
if(countA==1) p(bridge); 
v(mutexA); 
p(mutex); 
过桥; 
v(mutex); 
p(mutexA); countA--; 
if(countA==0) v(bridge); 
v(mutexA); 
} 
process west-to-east-j();//j=1,2,3….. 
{ 
{ p(mutexB); 
countB++; 
if(countB==1) p(bridge); 
v(mutexB); 
p(mutex); 
过桥; 
v(mutex); 
p(mutexB); 
countB--; 
if(countB==0) v(bridge); 
v(mutexB); 
}

类型2.一次能过多辆车

1.问题描述
东西向汽车驶过独木桥,为了保证交通安全,只要桥上无车,则允许一方的汽车过桥,待其全部过完后才允许另一方的汽车过桥,桥面上一次能过多辆车。请用信号量和pv操作写出汽车过独木桥问题的同步算法。
2.进程设计
两类进程:从东到西的汽车 PA 和从西到东的汽车 PB

(1)PA 进程:每辆汽车从东到西过桥的一次活动为一个进程
(2)PB 进程:每辆汽车从西到东过桥的一次活动为一个进程

3.信号量设计
(1)mutex1:用于 PA 进程之间对统计信息进行修改时的互斥信用量,初值为 1
(2)mutex2:用于 PB 进程之间对统计信息进行修改时的互斥信用量,初值为 1
(3)bridge:两个方向的汽车过桥的时的信号量,两个方向竞争此信号量,竞争成功的一方获得过桥资格,初值为 1
(4)number:同一方向过桥时的信号量,初值为 k
4.算法设计

semaphore mutex1=1, mutex2=1,bridge=1,number=k;int count1=0,count2=0; 
cobegin 
process PA_i()//i=1,2,….. 
{ 
p(mutex1); //对统计量 count1 写操作的互斥信号量 
count1++; 
If(count1==1) 
p(bridge)//第一个从东到西的汽车竞争桥的互斥信号量 
v(mutex1); 
p(number);// 同一方向的汽车过桥,同时可以过 k 辆 
过桥; 
V(number); 
p(mutex1); //对统计量 count1 写操作的互斥信号量 
coun1--; 
If(count1==0)v(bridge)//最后一个从东到西的汽车释放桥的互斥信号量 
v(mutex1); 
}process PB_j()//j=1,2,….. 
{ 
p(mutex2); //对统计量 count1 写操作的互斥信号量 
count2++; 
If(count2==1) p(bridge)//第一个从东到西的汽车竞争桥的互斥信号量 
v(mutex2); 
p(number);// 同一方向的汽车过桥,同时可以过 k 辆 
过桥; 
V(number); 
p(mutex2); //对统计量 count1 写操作的互斥信号量 
coun2--; 
If(count2==0)v(bridge)//最后一个从东到西的汽车释放桥的互斥信号量 
v(mutex2); 
} 
coend 

四、总结

读者写者问题和生产者消费者问题的区别在于:
(1)同一时期内生产者消费者问题可以交替执行;而读者写者问题在同一时期内只能由一方执行,当开始执行时必须执行完所有读者(或写者),另外一方才能开始执行。
(2)生产者消费者共享的缓存区必须要互斥;读者写者共享的文件不一定需要互斥,当限制只有不可同时读或不可同时写时共享的文件才需要互斥。
(3)独木桥问题有点特殊,代码中未体现出同步,当一方的车辆全部通过桥面时,释放桥的使用权,由于全部车辆已经通过,目前这一方已经没有车辆了,自然另一方就会抢到桥的使用权,然后开始过桥,如此反复,从而体现出了同步。

附代码:

//读者优先

/**1、首先当读者获得临界区的访问权,则此时的readcount  > 0 则读者尚未释放fmutex则写者就不能获得临界区的访问权,有一个被阻塞在fumtex信号中,其余的被塞    在Entmutex信号中,则只有当读者访问完毕,写者才有机会获得临界区的访问权2、若写者获得临界区的访问权,而且有源源不断的写着进程过来,那么读者能不能抢得临界区的访问权呢?答案是肯定的,因为考虑此时的读者进程阻塞情况,有一个读者进程阻塞在fmutex中,其余的读者均阻塞在Rmutex,而写者进程呢,由于Entemutex的存在每个时刻只有一个一个写者进程阻塞在fmutex中,其余的全被阻塞在Entmutex中,则当写者进程访问完毕后,此时阻塞在fmutex中的进程只有读者进程,则也就只有读者进程先被激活访问
*/mutex = 1    //读者、写者进程访问文件信号量变量,保证了读者与写者、写者与写者之间的互斥访问
Rmutex = 1   //实现对readcount的互斥访问
Entmutex =1  //若写者获得临界区的访问权,而且不断有写者进程过来,//那么读者将不能抢得临界区的访问权
readcount = 0
Read()
{while(1){wait(Rmutex) ;if(0 == readcount)wait(mutex) ;readcount ++ ;signal(Rmutex) ;-----------------------------| perform reading operation |-----------------------------wait(Rmutex);readcount --;if(0 == readcount)signal(mutex)signal(Rmutex) ;}
}
Writer()
{while(1){//保证每次阻塞在mutex中的写者进程只有一个,//确保当前写者写完,若还有写者等待,则会被卡在Entmutex,读者不需要等待wait(Entmutex)wait(mutex)-----------------------------| perform writing operation |-----------------------------signal(mutex)signal(Entmutex)}
}

//写者优先

/**
1.当读者获得了访问临界区的权利时,且读者进程访问的很密集时(即很多读者都需要访问),写者如何抢得访问权。
由于Entmutex的存在每次阻塞在Quemutex中的读者进程最多只有一个,而当读者进程访问时,写着进程一个被阻塞在Quemutex中,其余的全部阻塞在Wcount中,当读者访问完毕,释放Quemutex,此时,阻塞在其中的进程只有写者进程,则写着进程得到激活
2.当写者获得临界区的访问权时,读者只能等到临界区空闲时才能得到临界区访问权。
因为当写者获得临界区时,所有的读者都会阻塞在Entmutex信号和QUemutex信号中。 而只有最后一个写者访问完临界区时,才会Signal(Qmutex), 使得阻塞在fmutex中唯一的读者获得临界区访问权。
*/
Entemutex = 1
Quemutex = 1
Rmutex = 1
Wmutex = 1
mutex = 1 
readcount = 0Reader()
{while(1){wait(Entemutex)wait(Quemutex)wait(Rmutex)if(0 == readcount)wait(mutex)readcount++signal(Rmutex)signal(Quemutex)signal(Entemutex)-----------------------------| perform reading operation |-----------------------------wait(Rmutex)readcount--if(readcount == 0)signal(mutex)signal(Rmutex)}
}
writer()
{while(1){wait(Wmutex)if(writecount == 0)wait(Quemutex)writecount++signal(Wmutex)wait(mutex)-----------------------------| perform writing operation |-----------------------------signal(mutex)wait(Wmutex)writecount--if(writecount == 0)signal(Quemutex)signal(Wmutex)}
}

//公平竞争

Reader()
{while(1){wait(Quemutex)wait(Rmutex)if(0 == readcount)wait(mutex)readcount++signal(Rmutex)signal(Quemutex)-----------------------------| perform reading operation |-----------------------------wait(Rmutex)readcount--if(readcount == 0)signal(mutex)signal(Rmutex)}
}writer()
{while(1){wait(Quemutex)wait(mutex)-----------------------------| perform writing operation |-----------------------------signal(mutex)signal(Quemutex)}
}

教材原文:

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


http://chatgpt.dhexx.cn/article/wtuwhTDY.shtml

相关文章

四、操作系统——读者写者问题(详解)

一、问题描述: 二、需要满足的条件: 写进程与写进程之间必须互斥的写入数据(因为如果两个写进程同时对共享数据中的区域A中的数据进行写操作的话,会导致数据错误覆盖的问题)写进程与读进程之间必须互斥的访问共享数据…

锁机制:读者写者问题 Linux C

最近碰到一些锁机制的问题,想起大三的时候做过的一个小课设,记录复习一下。 问题描述: 一个数据文件可以被多个进程共享,其中,有些进程要求读(reader进程),而另一些进程要求对数据…

写优先的读者写者问题(Java实现)

该题系吉林大学19级软件学院操作系统课设题之一 先输入初始时的写者读者情况,优先级顺序做了随机处理 代码如下 GUI: import javax.swing.*; import javax.swing.border.Border; import javax.swing.text.BadLocationException; import javax.swing.tex…

操作系统读者写者问题代码实现

问题分析: 读者优先: 读者进程执行: 无其他读者写者, 直接执行有写者等, 但其他读者在读, 直接读有写者写, 等待写者进程执行: 无其他读写者, 直接执行有其他读写者, 等待 写者优先: 读者进程执行: 如果此时没有写者等待, 直接执行如果有写者等待, 那么等待写者…

读者写者问题详解 操作系统

2.16 读者写者问题 抽象解释 多个进程访问一个共享的数据区读者(读进程)只能读数据,写者(写进程)只能写数据适用于数据库、文件、内存、寄存器等数据区的访问模型如12306购票系统,由于用户量庞大和数据量…

同步机制—读者写者问题

【实验目的】 理解临界区和进程互斥的概念,掌握用信号量和PV操作实现进程互斥的方法。 【实验内容】 在windows或者linux环境下编写一个控制台应用程序,该程序运行时能创建N个线程,其中既有读者线程又有写者线程,它们按照事先设计…

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

一、问题描述 要求: 1、允许多个读者可以同时对文件执行读操作。 2、只允许一个写者往文件中写信息。 3、任一写者在完成写操作之前不允许其他读者或写者工作。 4、写者执行写操作前,应让已有的读者和写者全部退出。 二、问题分析 读者写者问题最核心的问题是如何处理…

【操作系统-进程】PV操作——读者写者问题

文章目录 读者写者问题万能模板万能模板 1——读进程优先万能模板 2——读写公平法万能模板 3——写进程优先 题目 1:南北过桥问题题目 2:录像厅问题题目 3:更衣问题 读者写者问题万能模板 读者写者问题,其本质就是连续多个同类进…

经典进程同步问题(三)——读者写者问题

目录 一、问题描述 二、解题思路 2.1 读者优先算法 2.2 写者优先算法 2.3 读写公平 三、源码实现 3.1 读者优先 3.2 写者优先 3.3 读写平等 一、问题描述 一个数据问价或记录可以被多个进程共享,我们把只读该文件的进程称为“读者进程”,其他进…

2. 堆与栈的区别

2. 堆与栈的区别 在理解这两个概念时,需要放到具体的场景下,因为不同场景下,堆与栈代表不同的含义。一般情况下,有两层含义: (1)程序内存布局场景下,堆与栈表示的是两种内存管理方式…

栈与堆的区别(内存分配与数据结构)

参考自https://blog.csdn.net/K346K346/article/details/80849966/ 堆(Heap)与栈(Stack)包含两层含义: 程序内存布局场景下的内存管理方式数据结构中的两种常见的数据结构 1. 程序内存分配中的堆与栈 1.1 栈介绍 …

C语言里栈和堆的区别整理

这里说的是C语言程序内存分配中的堆和栈。下面先谈谈C语言的内存管理: 可执行程序在存储时(没有调到内存)分为代码区(text)、数据区(data)和未初始化数据区(bss)3个部分。…

看懂堆与栈的区别与联系

<div class"simditor-body clearfix" style"height: auto; overflow: inherit;"><h2> <strong>  堆和栈概要</strong></h2>在计算机领域&#xff0c;堆栈是一个不容忽视的概念&#xff0c;堆栈是两种数据结构。堆栈都是一…

C语言:栈和堆的区别

c语言五大内存分区 栈区&#xff08;stack&#xff09;:存放函数形参和局部变量&#xff08;auto类型&#xff09;&#xff0c;由编译器自动分配和释放 堆区&#xff08;heap&#xff09;:该区由程序员申请后使用&#xff0c;需要手动释放否则会造成内存泄漏。如果程序员没有手…

什么是栈(Stack)?什么是堆(Heap)?栈和堆的区别是什么?

原参考地址&#xff1a;https://zhidao.baidu.com/question/36918441.html 栈&#xff1a;由操作系统自动分配释放 &#xff0c;存放函数的参数值&#xff0c;局部变量du的值等。其操作方式类似于数据结构中的栈&#xff1b; 堆&#xff1a; 一般由程序员分配释放&#xff0c…

堆和栈的概念和区别

在说堆和栈之前&#xff0c;我们先说一下JVM&#xff08;虚拟机&#xff09;内存的划分&#xff1a; Java程序在运行时都要开辟空间&#xff0c;任何软件在运行时都要在内存中开辟空间&#xff0c;Java虚拟机运行时也是要开辟空间的。JVM运行时在内存中开辟一片内存区域&#x…

堆与栈的区别详细总结

1、堆与栈的区别详细总结_Fighting的博客-CSDN博客_堆和栈的区别 2、堆和栈的区别 - 江雨牧 - 博客园 3、堆和栈的区别_内外皆秀的博客-CSDN博客_堆和栈的区别 4、一文读懂堆与栈的区别_恋喵大鲤鱼的博客-CSDN博客_堆和栈的区别 一般情况下&#xff0c;如果有人把堆栈合起来…

栈和堆的区别

栈和堆的区别 前面已经介绍过&#xff0c;栈是由编译器在需要时分配的&#xff0c;不需要时自动清除的变量存储区。里面的变量通常是局部变量、函数参数等。堆是由malloc()函数分配的内存块&#xff0c;内存释放由程序员手动控制&#xff0c;在C语言为free函数完成。栈和堆的主…

Struts常见面试题

Struts分为Struts1和Struts2&#xff0c;默认情况下指的是Struts2&#xff0c;Struts1除非特别说明。 1、Struts2 中的 # 和 % 分别是做什么的&#xff1f; &#xff08;1&#xff09;使用#获取 context 里面的数据 <s:iterator value “list” var”user”> <s:p…

关于Struts2的笔试题(一)

一. struts2框架中struts.xml配置文件,package标签的属性有那几个?各有什么功能? 1.name属性 作用:定义一个包的名称&#xff0c;它必须唯一。 2.namespace属性 作用:主要是与action标签的name属性联合使用来确定一个action 的访问路径 3.extends属性 作用:指定继承自哪个…