读者和写者问题
实验五 读者-写者问题
实验题目:实验五读者-写者问题完成人:报告日期:一、实验内容简要描述1)创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
2)读者-写者问题的读写操作限制(包括读者优先和写者优先):写-写互斥,即不能有两个写者同时进行写操作。
读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
●读-读允许,即可以有一个或多个读者在读。
3)读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
4)写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
5)运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、程序设计1、设计思路将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。
2、主要数据结构1)读者优先读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=0时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_count变量。
因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读-写互斥,当read_count=l时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权。
读者-写者问题说明书
《操作系统原理》课程设计任务书题目:读者-写者问题的实现学生姓名:李志旭学号:13740113 班级:_13级软件工程_题目类型:软件工程(R)指导教师:陈文娟、马生菊一、设计目的学生通过该题目的设计过程,掌握读者、写者问题的原理、软件开发方法并提高解决实际问题的能力。
二、设计任务编写程序实现读者优先和写者优先问题:读者-写者问题的读写操作限制(包括读者优先和写者优先)写-写互斥:不能有两个写者同时进行写操作读-写互斥:不能同时有一个线程在读,而另一个线程在写。
读-读允许:可以有一个或多个读者在读。
三、设计要求1.分析设计要求,给出解决方案(要说明设计实现所用的原理、采用的数据结构)。
2.设计合适的测试用例,对得到的运行结果要有分析。
3.设计中遇到的问题,设计的心得体会。
4.文档:课程设计打印文档每个学生一份,并装在统一的资料袋中,资料袋前面要贴有学校统一的资料袋封面。
四、提交的成果1. 课程设计说明书内容包括(1) 封面(学院统一印制);(2) 课程设计任务书;(3) 中文摘要150字;关键词3-5个;(4) 目录;(5) 正文;(设计思想;各模块的伪码算法;函数的调用关系图;测试结果等)(6) 设计总结;(7) 参考文献;(8) 致谢等。
注:每一部分是单独的一章,要另起一页写。
2. 排版要求(1) 所有一级标题为宋体三号加粗(即上面写的2~8部分,单独一行,居中)(2) 所有二级标题为宋体四号加粗(左对齐)(3) 所有三级标题为宋体小四加粗(左对齐)(4) 除标题外所有正文为宋体小四,行间距为固定值22磅,每个段落首行缩进2字符(5) 目录只显示3级标题,目录的最后一项是无序号的“参考文献资料”。
3. 其他要求(班长负责,务必按照以下方式建文件夹)(1) 以班级为单位刻录光盘一张,光盘以班级命名,例如:“10级计算机科学与技术1班”;(2) 光盘内每人一个文件夹,以学号姓名命名——如“10730101 陈映霞”,内容包括任务书、设计文档。
读者写者问题描述
读者写者问题描述嘿,你问读者写者问题啊?那我给你讲讲哈。
咱就说啊,这读者写者问题呢,就好比一个图书馆。
有很多人想去看书,这就是读者。
还有人想去写书,那就是写者。
有一回啊,我去图书馆。
那里面好多人都在安静地看书呢。
这时候就相当于有很多读者在享受知识。
突然,有个作家模样的人来了,他想找个地方坐下来写书。
这就是写者出现了。
这时候问题就来了。
如果读者和写者同时在图书馆里,会咋样呢?如果读者一直在看书,写者就没办法好好写书,因为他会觉得被打扰了。
反过来,如果写者一直在写书,读者也没办法好好看书,因为他们不知道啥时候能看到新的内容。
就像我在图书馆里,我正看得入迷呢,突然那个作家开始大声地思考他的情节,哎呀,那可把我烦死了。
我就想,你能不能安静点啊,让我好好看书嘛。
这就像读者希望写者不要打扰他们一样。
那怎么办呢?就得有个规则。
比如说,让写者先等读者都看完书走了,他再开始写书。
或者让读者在写者写书的时候,稍微安静一点,不要弄出太大动静。
我记得有一次,我在图书馆里,有个写者特别有礼貌。
他进来的时候,看到很多读者,就悄悄地找了个角落坐下,等大家都看得差不多了,他才开始动笔。
这样大家都能和谐共处了。
读者写者问题就是要找到一个平衡,让读者能愉快地看书,写者也能安心地写书。
不能让一方太强势,影响了另一方。
就像在生活中,我们也会遇到类似的情况。
比如说,一个办公室里,有人在安静地工作,有人在讨论问题。
这时候就得互相体谅,不能太吵了,影响别人工作。
总之啊,读者写者问题就是要解决大家在共享资源的时候,如何和谐相处的问题。
嘿嘿,你明白了不?。
读者写者问题
. ..一设计概述所谓读者写者问题,是指保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书,并且,读者必写者优先,也就是说,读者和写者同时提出请求时,读者优先。
当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S来当前是否可操作。
信号量机制是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者问题则是这一机制的一个经典范例。
与记录型信号量解决读者—写者问题不同,信号量机制它增加了一个限制,即最多允许RN个读者同时读。
为此,又引入了一个信号量L,并赋予初值为RN,通过执行wait(L,1,1)操作,来控制读者的数目,每当有一个读者进入时,就要执行wait(L,1,1)操作,使L的值减1。
当有RN个读者进入读后,L便减为0,第RN+1 个读者要进入读时,必然会因wait(L,1,1)操作失败而堵塞。
对利用信号量来解决读者—写者问题的描述如下:Var RN integer;L,mx:semaphore: =RN,1;BeginParbeginReader :beginRepeatSwait(L,1,1);Swait(mx,1,0);.Perform reader operation;Ssignal(L,1);Until false;EndWriter :beginRepeatSwait(mx ,1,1,l,RN,0);Perform writer operation;Ssignal(mx,1);Until false;EndParendEnd其中,Swait(mx,1,0)语句起着开关作用,只要无Writer进程进入些,mx=1,reader进程就都可以进入读。
但是要一旦有Writer进程进入写时,其MX=0,则任何reader进程就都无法进入读。
读者于写者问题课程设计
读者于写者问题课程设计一、教学目标本课程的教学目标是帮助学生理解并掌握“读者于写者问题”的相关概念和理论,培养学生对于文本的深入解读和批判性思维能力。
具体分为以下三个部分:知识目标:学生能够准确地掌握读者反应理论和作者意图理论的基本概念,了解不同读者和写者对于文本的影响和作用。
技能目标:学生能够运用所学的理论知识,对于给定的文本进行深入解读和分析,并能够就文本内容进行批判性的思考和讨论。
情感态度价值观目标:通过对于不同读者和写者问题的探讨,培养学生尊重多元观点和包容差异的态度,增强对于文本的理解和欣赏能力。
二、教学内容本课程的教学内容主要包括读者反应理论和作者意图理论两个部分。
具体内容包括:1.读者反应理论:介绍读者反应理论的基本概念和主要观点,分析读者的阅读过程和文本理解的影响因素。
2.作者意图理论:讲解作者意图理论的基本原理和应用方法,探讨作者的意图和文本的意义之间的关系。
3.读者与写者的互动:讨论读者和写者之间的相互作用和平衡,分析读者对于文本的影响和写者的创作意图的实现。
三、教学方法为了达到本课程的教学目标,将采用多种教学方法进行教学,包括:1.讲授法:通过教师的讲解和阐述,系统地传授读者反应理论和作者意图理论的相关知识。
2.讨论法:学生进行小组讨论和全班讨论,鼓励学生提出自己的观点和思考,培养学生的批判性思维能力。
3.案例分析法:通过分析具体的案例和文本,让学生亲身体验和理解读者反应理论和作者意图理论的应用和意义。
四、教学资源为了支持和丰富本课程的教学内容和方法,将利用多种教学资源,包括:1.教材:选用合适的教材,提供全面系统的读者反应理论和作者意图理论的知识框架。
2.参考书:推荐相关的参考书籍,供学生进一步深入学习和研究。
3.多媒体资料:利用多媒体资料,如视频、音频、图片等,增加教学的趣味性和形象性。
4.实验设备:根据需要,安排适当的实验设备,让学生进行实证研究和实践操作。
五、教学评估本课程的评估方式包括平时表现、作业和考试三个部分,以全面客观地评价学生的学习成果。
读者写者问题
3)读读允许,即可以有2个以上的读者同时读
将所有的读者与所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。读者写者问题的定义如下:有一个许多进程共享的数据区,这个数据区可以就是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)与一些只往数据区写数据的进程(Writer),此外还需要满足以下条件:1)任意多个读进程可以同时读这个文件;2)一次只有一个写进程可以往文件中写;3)如果一个写进程正在进行操作,禁止任何读进程度文件。我们需要分两种情况实现该问题:
一设计概述
所谓读者写者问题,就是指保证一个writer进程必须与其她进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述,有一群写者与一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但就是,只能有一个写者在写书,并且,读者必写者优先,也就就是说,读者与写者同时提出请求时,读者优先。当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S来当前就是否可操作。
信号量机制就是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者问题则就是这一机制的一个经典范例。
与记录型信号量解决读者—写者问题不同,信号量机制它增加了一个限制,即最多允许RN个读者同时读。为此,又引入了一个信号量L,并赋予初值为RN,通过执行wait(L,1,1)操作,来控制读者的数目,每当有一个读者进入时,就要执行wait(L,1,1)操作,使L的值减1。当有RN个读者进入读后,L便减为0,第RN+1个读者要进入读时,必然会因wait(L,1,1)操作失败而堵塞。对利用信号量来解决读者—写者问题的描述如下:
读者-写者问题解答
2.读者—写者问题读者—写者问题(Readers-Writers problem)也是一个经典的并发程序设计问题,是经常出现的一种同步问题。
计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。
就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求:(1)允许多个读者同时执行读操作;(2)不允许读者、写者同时操作;(3)不允许多个写者同时操作。
Reader和Writer的同步问题分为读者优先、弱写者优先(公平竞争)和强写者优先三种情况,它们的处理方式不同。
(1)读者优先。
对于读者优先,应满足下列条件:如果新读者到:①无读者、写者,新读者可以读;②有写者等待,但有其它读者正在读,则新读者也可以读;③有写者写,新读者等待。
如果新写者到:①无读者,新写者可以写;②有读者,新写者等待;③有其它写者,新写者等待。
单纯使用信号量不能解决读者与写者问题,必须引入计数器rc 对读进程计数;rc_mutex 是用于对计数器rc 操作的互斥信号量;write表示是否允许写的信号量;于是读者优先的程序设计如下:int rc=0; //用于记录当前的读者数量semaphore rc_mutex=1; //用于对共享变量rc 操作的互斥信号量semaphore write=1; //用于保证读者和写者互斥地访问的信号量void reader() /*读者进程*/do{P(rc_mutex); //开始对rc共享变量进行互斥访问rc ++; //来了一个读进程,读进程数加1if (rc==1) P(write);//如是第一个读进程,判断是否有写进程在临界区,//若有,读进程等待,若无,阻塞写进程V(rc_mutex); //结束对rc共享变量的互斥访问读文件;P(rc_mutex); //开始对rc共享变量的互斥访问r c--; //一个读进程读完,读进程数减1if (rc == 0) V(write);//最后一个离开临界区的读进程需要判断是否有写进程//需要进入临界区,若有,唤醒一个写进程进临界区V(rc_mutex); //结束对rc共享变量的互斥访问} while(1)void writer() /*写者进程*/do{P(write); //无读进程,进入写进程;若有读进程,写进程等待写文件;V(write); //写进程完成;判断是否有读进程需要进入临界区,//若有,唤醒一个读进程进临界区} while(1)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
写优先”策略的“读者-写者”问题
采用“写优先”策略的“读者-写者”问题学院计算机科学与技术专业计算机科学与技术学号学生姓名指导教师姓名2014-3-11目录一、设计目的与内容 ................................................ 错误!未定义书签。
(1 )、课程设计的目的 (1)(2 ) 、课程设计的内容 (1)(3 ) 、课程设计的要求 (1)二、算法的基本思想 ................................................ 错误!未定义书签。
三、模块流程图......................................................... 错误!未定义书签。
四、测试结果............................................................. 错误!未定义书签。
五、结论..................................................................... 错误!未定义书签。
六、源程序................................................................. 错误!未定义书签。
一、设计目的与内容(1)课程设计的目的:操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决问题的机会。
●进一步巩固和复习操作系统的基础知识。
●培养学生结构化程序、模块化程序设计的方法和能力。
●提高学生调试程序的技巧和软件设计的能力。
●提高学生分析问题、解决问题以及综合利用C语言进行程序设计的能力。
(2) 课程设计的内容:用高级语言编写和调试一个采用“写优先”策略的“读者—写者”问题的模拟程序。
(3) 课程设计的要求:1.读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入。
4.9 经典进程同步问题:读者-写者问题
4.9 经典进程同步问题:读者-写者问题(the readers-writers problem)
问题描述:对共享资源的读写操作,任一时刻“写者”最多只允许一个,而“读者”则允许多个,要求:
●“读-写” 互斥
●“写-写” 互斥
●“读-读” 允许
设置如下信号量:
Wmutex表示“允许写”,初值是1;
Rmutex表示对Rcount的互斥操作,初值是1。
公共变量Rcount表示“正在读”的进程数,初值是0。
由问题描述,我们可以分析出:
只要一个reader进程在读,便不允许writer进程去写;
仅当Rcount=0,reader进程才需要执行P(Wmutex)操作;
仅当reader进程执行了Rcount减1操作后,其值为0时,才须执行V(Wmutex)操作。
用信号量和P、V原语解决读者-写者问题如下:。
读者写者问题写者优先参考答案完整版
读者写者问题写者优先参考答案HUA system office room 【HUA16H-TTMS2A-HUAS8Q8-HUAH1688】【写者优先】在读者、写者问题中,如果总有读者进程进行读操作,会造成写者进程永远都不能进行写操作(读者优先),即所谓的写者饿死现象。
给出读者、写者问题的另一个解决方案:即保证当有一个写者进程想写时,不允许读者进程再进入,直到写者写完为止,即写者优先。
让我们先回顾读者写者问题[1]:一个数据对象若被多个并发进程所共享,且其中一些进程只要求读该数据对象的内容,而另一些进程则要求写操作,对此,我们把只想读的进程称为“读者”,而把要求写的进程称为“写者”。
在读者、写者问题中,任何时刻要求“写者”最多只允许有一个执行,而“读者”则允许有多个同时执行。
因为多个“读者”的行为互不干扰,他们只是读数据,而不会改变数据对象的内容,而“写者”则不同,他们要改变数据对象的内容,如果他们同时操作,则数据对象的内容将会变得不可知。
所以对共享资源的读写操作的限制条件是:允许任意多的读进程同时读;一次只允许一个写进程进行写操作;如果有一个写进程正在进行写操作,禁止任何读进程进行读操作。
为了解决该问题,我们只需解决“写者与写者”和“写者与第一个读者”的互斥问题即可,为此我们引入一个互斥信号量Wmutex,为了记录谁是第一个读者,我们用一个共享整型变量Rcount 作一个计数器。
而在解决问题的过程中,由于我们使用了共享变量Rcount,该变量又是一个临界资源,对于它的访问仍需要互斥进行,所以需要一个互斥信号量Rmutex,算法如下:}}现在回到【写者优先】优先问题【写者优先】在读者、写者问题中,如果总有读者进程进行读操作,会造成写者进程永远都不能进行写操作(读者优先),即所谓的写者饿死现象。
给出读者、写者问题的另一个解决方案:即保证当有一个写者进程想写时,不允许读者进程再进入,直到写者写完为止,即写者优先。
经典同步问题读者-写者问题
经典同步问题读者-写者问题读者-写者问题在读者-写者问题中,只对共享数据进⾏读取的进程为读者进程,修改共享数据的进程称为写者进程。
多个读者可同时读取共享数据⽽不会导致出现错误,但是任何时刻多个写者进程不能同时修改数据,写者进程和读者进程也不能同时访问共享数据。
读者-写者问题的解决策略有不同的倾向。
读者优先需要⽤到的共享变量:semaphore rw_mutex = 1; // 读者与写者互斥访问共享数据的互斥信号量semaphore mutex = 1; // 多个读者进程互斥修改当前读者进程数量的信号量int read_count = 0; // 系统当前读者进程数量写者进程结构do {wait(rw_mutex);.../* 修改共享数据 */...signal(rw_mutex);}while(true);读者进程结构do {wait(mutex); // 获取修改读者进程数量的互斥信号量,该操作在请求rw_mutex之前,防⽌出现死锁read_count++;if(read_count == 1) // 判断当前是否为第⼀个读者进程wait(rw_mutex); // 如果是就需要请求访问共享数据的互斥信号量signal(mutex); // read_count修改后释放信号量.../* 读取数据 */...wait(mutex); // 获取修改读者进程数量的互斥信号量read_count--;if(read_count == 0) // 判断当前进程是否为最后⼀个读者进程signal(rw_mutex); // 如果是则释放共享数据的互斥信号量,以允许写者进程操作共享数据signal(mutex);}while(true);读者优先有可能导致写者进程产⽣饥饿现象,当系统中不断出现读者进程时,写者进程始终⽆法进⼊临界区。
写者优先需要⽤到的共享变量:semaphore rw_mutex = 1; // 读者与写者互斥访问共享数据的互斥信号量semaphore r_mutex = 1; // 互斥修改当前读取⽂件的进程数semaphore w_mutex = 1; // 互斥修改当前修改⽂件的进程数semaphore enter_mutex = 1; // 获取申请访问⽂件的权限int read_count = 0; // 系统当前读者进程数量int write_count = 0; // 系统当前写者进程数量写者进程结构do {wait(w_mutex); // 新的写者进程进⼊,获取修改写者进程数量的权限write_count++;if(write_count == 1) // 判断当前是否为第⼀个写者进程wait(enter_mutex); // 阻断后续到达的读者进程signal(w_mutex);wait(rw_mutex); // 获取访问⽂件的权限,⽂件可能被其它写者进程占⽤,或者等待最后⼀个读者进程释放.../* 修改数据 */...wait(rw_mutex);wait(w_mutex);write_count--;if(write_count == 0) // 当所有写者进程都放弃使⽤⽂件时,运⾏读者进程申请访问⽂件signal(enter_mutex);signal(mutex);}while(true);读者进程结构do {wait(enter_mutex); // 获取申请访问⽂件的权限wait(r_mutex);read_count++;if(read_count == 1) // 判断当前是否为第⼀个读者进程wait(rw_mutex); // 占⽤⽂件signal(r_mutex);signal(enter_mutex);.../* 读取数据 */...wait(r_mutex);read_count--;if(read_count == 0)signal(rw_mutex);signal(r_mutex);}while(true);写者优先有可能导致读者进程产⽣饥饿现象,当系统中不断出现写者进程时,读者进程始终⽆法进⼊临界区。
读者-写者问题解答
2.读者—写者问题读者—写者问题(Readers-Writers problem)也是一个经典的并发程序设计问题,是经常出现的一种同步问题。
计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。
就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求:(1)允许多个读者同时执行读操作;(2)不允许读者、写者同时操作;(3)不允许多个写者同时操作。
Reader和Writer的同步问题分为读者优先、弱写者优先(公平竞争)和强写者优先三种情况,它们的处理方式不同。
(1)读者优先。
对于读者优先,应满足下列条件:如果新读者到:①无读者、写者,新读者可以读;②有写者等待,但有其它读者正在读,则新读者也可以读;③有写者写,新读者等待。
如果新写者到:①无读者,新写者可以写;②有读者,新写者等待;③有其它写者,新写者等待。
单纯使用信号量不能解决读者与写者问题,必须引入计数器rc 对读进程计数;rc_mutex 是用于对计数器rc 操作的互斥信号量;write表示是否允许写的信号量;于是读者优先的程序设计如下:int rc=0; //用于记录当前的读者数量semaphore rc_mutex=1; //用于对共享变量rc 操作的互斥信号量semaphore write=1; //用于保证读者和写者互斥地访问的信号量void reader() /*读者进程*/do{P(rc_mutex); //开始对rc共享变量进行互斥访问rc ++; //来了一个读进程,读进程数加1if (rc==1) P(write);//如是第一个读进程,判断是否有写进程在临界区,//若有,读进程等待,若无,阻塞写进程V(rc_mutex); //结束对rc共享变量的互斥访问读文件;P(rc_mutex); //开始对rc共享变量的互斥访问r c--; //一个读进程读完,读进程数减1if (rc == 0) V(write);//最后一个离开临界区的读进程需要判断是否有写进程//需要进入临界区,若有,唤醒一个写进程进临界区V(rc_mutex); //结束对rc共享变量的互斥访问} while(1)void writer() /*写者进程*/do{P(write); //无读进程,进入写进程;若有读进程,写进程等待写文件;V(write); //写进程完成;判断是否有读进程需要进入临界区,//若有,唤醒一个读进程进临界区} while(1)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
读者和写者问题
学号:课程设计课程名称操作系统学院计算机科学与技术学院专业软件工程专业班级姓名指导教师2014——2015学年第1学期目录目录 ....................................................................................................................................... 错误!未定义书签。
1 设计概述 (3)1.1问题描述: (3)1.2问题解读及规则制定 (3)2课程设计目的及功能 (3)2.1 设计目的 (3)2.2 设计功能 (3)3模块介绍 (3)3.1函数原型 (3)3.2 PV操作代码 (4)4测试用例,运行结果与运行情况分析 (6)4.1测试用例 (6)4.2运行结果 (7)4.3运行情况分析 (9)5自我评价与总结 (9)6 参考文献 (10)7 附录:(完整代码) (10)实现读者写者(Reader-Writer Problem)问题1 设计概述1.1问题描述:通过研究Linux的线程机制和信号量实现读者写者(Reader-Writer)问题并发控制。
1.2问题解读及规则制定一个数据文件或记录可被多个进程所共享,我们将其中只要求读该文件的进程称为读者,其他进程称为写者.多个读者和多个写者进程在某个时间段内对该文件资源进行异步操作,也就是说允许多个进程同时读一个共享对象,但不允许一个写进程和其他读进程或写进程同时访问共享对象,因此,所谓"读者--写者问题"就是指必须保证一个写进程和其他进程(写进程或者读进程)互斥地访问共享对象的同步问题.两者的读写操作限制规则如下:(1)写--写互斥,即不允许多个写着同时对文件进行写操作(2)读--写互斥,即不允许读者和写者同时对文件分别进行读写操作(3)读—读允许,即允许多个读者同时对文件进行读操作2课程设计目的及功能2.1 设计目的通过实验模拟读者和写者之间的关系,了解并掌握他们之间的关系及其原理。
读者写入者问题
阅读者写入者问题实验目的通过经典的并发程序(同步)问题,理解临界区和进程互斥的概念,掌握用信号量和PV操作实现进程互斥的方法。
1、熟练使用VC6.0编译环境,调试并正确运行程序;2、阅读演示程序源代码,熟悉阅读者和写入者问题流程;3、理解源程序中管理阅读者和写入者权限的算法,及相关窗口操作;4、掌握信号量的使用;5、写出Reader ()和Writer ()函数伪码。
问题描述有一公用数据区,很多人要访问,其中一些需要阅读其中的信息,一些需要修改其中的信息。
阅读者可以同时访问数据区,而写入者只能互斥的访问数据区,不能与任何的进程一起访问数据区。
分析:读者和写者是两组并发进程,共享一组数据区,且满足:(1)n个读者正在读,则允许多个读者同时读;(读—读允许)(2)一个写者正在写,则禁止多个写者同时写;(写—写互斥)(3)n个读者正在读,则禁止写者同时写;(读—写互斥);(4)一个写者正在写,则禁止读者同时读;(读—写互斥)逻辑关系:对新读者:①无读者则读;②有读者则读;③无写者则读;④有写者则等。
对新写者:①无读者则写;②有读者则等;③无写者则写;④有写者则等。
优先级:①读者优先:读写同时等,则写等读读后写(写者可能饿死);②写者优先:读写同时等,则读等写写后读。
③无优先:先等先执行;伪代码(读者优先):(完整代码见附录)int rdc = 0; //读者计数semaphore data, mutex; //两个信号量handle Reading, Writing; //两个事件Reader{ ReaderState("读者%d正在等...\n", GetCurrentThreadId); //读者等P(Writing); //等待写事件释放文件空间P(&mutex); //占用计数空间rdc++; //多一个读者if (rdc == 1) //第一个读者V(&mutex); //释放计数空间ReaderState("读者%d正在读...\n", GetCurrentThreadId); //读者读P(&mutex); //占用计数空间ReaderState("读者%d结束读\n", GetCurrentThreadId); //读结束rdc--; //少一个读者if (rdc == 0) //最后一个读者V(Reading); //读完释放文件空间V1(&mutex); //释放计数空间return 0;}Writer{ WriterState("写者正在等\n");//写者等P(Reading);//等待读事件释放文件空间WriterState("写者正在写\n");//写者写WriterState("写者结束写\n");//写结束V(Writing); //写完释放文件空间return 0;}Main{ rdc = 0;int i;HANDLE hThread[Rd_No + 1];for (i = 1; i <= 2; i++) //启动i max个读者线程hThread[i] = (HANDLE)_beginthreadex(NULL, 0, Reader, NULL, 0, NULL);hThread[0] = (HANDLE)_beginthreadex(NULL, 0, Writer, NULL, 0, NULL);//启动写者线程for ( ; i <= Rd_No; i++) //最后启动其它读者结程hThread[i] = (HANDLE)_beginthreadex(NULL, 0, Reader, NULL, 0, NULL);WaitForMultipleObjects(Rd_No + 1, hThread, TRUE, INFINITE);for (i = 0; i < Rd_No + 1; i++)CloseHandle(hThread[i]);return 0;}说明:读者数宏定义,读者序号随机;写者唯一;均未循环完整代码见附录运行结果#define Rd_No 4 //4个读者1个写者#define Rd_No 7 //7个读者1个写者心得体会这一次操作系统实验课是通过信号量和pv操作实现经典算法问题——阅读者与写入者的问题。
阅读者写入者问题
二、阅读者写入者问题实验目的通过经典的并发程序(同步)问题,理解临界区和进程互斥的概念,掌握用信号量和PV操作实现进程互斥的方法。
问题描述有一公用数据区,读者写者要共同访问,其中一些需要阅读其中的信息,一些需要修改其中的信息。
阅读者可以同时访问数据区,而写入者只能互斥的访问数据区,不能与任何的进程一起访问数据区。
分析:读者和写者是两组并发进程,共享一组数据区,且满足:(1)n个读者正在读,则允许多个读者同时读;(读—读允许)(2)一个写者正在写,则禁止多个写者同时写;(写—写互斥)(3)n个读者正在读,则禁止写者同时写;(读—写互斥);(4)一个写者正在写,则禁止读者同时读;(读—写互斥)对策:对新读者:①无读者则读;②有读者则读;③无写者则读;④有写者则等。
对新写者:①无读者则写;②有读者则等;③无写者则写;④有写者则等。
伪代码:(完整代码见附录)int rdc = 0; //读者计数semaphore data, mutex; //两个信号量handle Reading, Writing; //两个事件void ReaderThreadState(char *R, ...) //读者线程输出void WriterThreadState(char *W) //写者线程输出int ReaderThread()//读者线程int WriterThread()//写者线程int main()//主函数//读者数由宏定义,序号随机//写者唯一ReaderThread://读者线程{ //读者等P(Writing); //等待写事件释放文件空间P(&mutex); //占用计数空间rdc++; //多一个读者if (rdc == 1) //第一个读者V(&mutex); //释放计数空间//读者读P(&mutex); //占用计数空间//读结束rdc--; //少一个读者if (rdc == 0) //最后一个读者V(Reading); //读完释放文件空间V1(&mutex); //释放计数空间return 0;}WriterThread://写者线程{ //写者等P(Reading);//等待读事件释放文件空间//写者写//写完V(Writing); //释放文件空间return 0;}Main//主函数{ HANDLE Event[Rd_No + 1];//所有线程集合for (i = 1; i <= 2; i++)//先启动2个读者线程(防止写者饿死)//启动写者线程for ( ; i <= Rd_No; i++)//后启动其它读者线程WaitForMultipleObjects(Rd_No + 1, Event, TRUE, INFINITE);for (i = 0; i < Rd_No + 1; i++)CloseHandle(Event[i]);//关闭进程}运行结果(#define Rd_No 7 //7个读者1个写者)心得体会这一次操作系统实验,是通过信号量和pv操作实现经典算法“阅读者与写入者问题”。
操作系统之读者与写者问题(C++)
printf("第%d位读者正在读。。。\n", myid);
Sleep(2000);//模拟读操作
printf("第%d位读者已完成\n", myid);
WaitForSingleObject(rc_mutex, INFINITE);//对rc互斥访问
ReleaseMutex函数的功能是释放互斥对象的控制权,可以理解为使一个特定的内核对象变为已通知状态。
4.测试及实验结果
4.1 实验结果
图4-1 第一次运行结果图
图4-2 第二次运行结果图
4.2 结果分析
根据图4-1的运行结果来分析,当第二位读者和第二位写者同时存在时,先运行的是写者进程,只有当写者进程完成操作后才能进行读者进程,根据图4-2的运行结果来分析,第一位读者进入后需等第四位写者完成写操作后才能开始读操作。总得来看,该程序得读者与写者得优先级其实是一样的,谁先创建的就谁先运行,但必须等上一个进程完成后才能运行下一个进程。
6.参考文献
[1]张玉生、刘炎、张亚红. C语言程序设计[M].上海交通大学出版社,2004
[2]陆丽娜.计算机操作系统[M].高等教育出版社. 2015.8
[3]李春葆.数据结构教程[M].清华大学出版社,2004
[4].陈向群,向勇等. Windows操作系统原理(第二版) [M]. 机械工业出版社,2004
rc -= 1;//读者数减1
if (rc == 0)
ReleaseMutex(w);//释放写互斥信号量
ReleaseMutex(rc_mutex);//释放互斥信号量rc_mutex
return 1;
读者写者问题-写者优先参考答案
读者写者问题-写者优先参考答案【写者优先】在读者、写者问题中,如果总有读者进程进行读操作,会造成写者进程永远都不能进行写操作(读者优先),即所谓的写者饿死现象。
给出读者、写者问题的另一个解决方案:即保证当有一个写者进程想写时,不允许读者进程再进入,直到写者写完为止,即写者优先。
让我们先回顾读者写者问题[1]:一个数据对象若被多个并发进程所共享,且其中一些进程只要求读该数据对象的内容,而另一些进程则要求写操作,对此,我们把只想读的进程称为“读者”,而把要求写的进程称为“写者”。
在读者、写者问题中,任何时刻要求“写者”最多只允许有一个执行,而“读者”则允许有多个同时执行。
因为多个“读者”的行为互不干扰,他们只是读数据,而不会改变数据对象的内容,而“写者”则不同,他们要改变数据对象的内容,如果他们同时操作,则数据对象的内容将会变得不可知。
所以对共享资源的读写操作的限制条件是:⏹允许任意多的读进程同时读;⏹一次只允许一个写进程进行写操作;如果有一个写进程正在进行写操作,禁止⋯⋯;P(Rmutex);Rcount = Rcount - 1;if (Rcount == 0) V(wmutex);V(Rmutex);}}void writer() /*写者进程*/{while (true){P(Wmutex);⋯⋯;write; /* 执行写操作 */⋯⋯;P(Wmutex);}}现在回到【写者优先】优先问题【写者优先】在读者、写者问题中,如果总有读者进程进行读操作,会造成写者进程永远都不能进行写操作(读者优先),即所谓的写者饿死现象。
给出读者、写者问题的另一个解决方案:即保证当有一个写者进程想写时,不允许读者进程再进入,直到写者写完为止,即写者优先。
【解题思路】在上面的读者写者问题基础上,做以下修改:⏹增加授权标志authFlag,当写者到来,发现有读者在读,则取消授权,然后等待缓冲区;⏹增加“等待授权计数器waitAuthCount”,写者离开时,如果waitAuthCount大于0,则迭代唤醒等待授权的读者;⏹读者到来,首先看授权标志,如果有授权标志,则继续,否则等待授权,即写者取消授权后,新来的读者不能申请缓冲区。
操作系统课程之“读者—写者问题教学探讨
操作系统课程之“读者—写者问题教学探讨摘要:针对操作系统教学中概念多而繁杂、容易混淆,初学者存在畏难情绪等问题,文章提出采取类比、逐层解剖、层层深入、循序渐进的教学方法,并以操作系统中的进程同步互斥问题中“读者-写者”问题为例,对其概念、算法进行形象启发、分层解剖的阐述,并结合多种教学方法,说明使学生能更深刻地理解进程同步互斥问题的方法。
教学实践表明其效果良好。
关键词:操作系统;分层解剖;读者-写者问题;PV原语;教学实践操作系统是计算机专业的一门核心课程(图1),其在计算机系统中的特殊地位,使得该课程的学习在整个计算机学科教育中显得尤为重要。
作为一门理论性和实践性并重的课程,它具有概念多、算法较抽象的特点,同时又涉及了程序设计语言、软件工程思想、算法设计、计算机系统结构、网络等相关知识。
枯燥的理论讲述往往使学生感到抽象、难懂,进而产生厌学的思想。
尽管近年来一些高校在加强理论教学的同时,引入对操作系统内核的分析,如Linu某操作系统,在教学实践方面取得了一点的成效,但是对于初学者和教师而言,在一个学期内课时数不变的情况下,完成教与学的工作显得有点心有余而力不足。
为了在有限的教学时间内,提高教学效率,既让学生深入理解理论知识,又能借助PV操作原语来验证操作系统的算法思想,笔者根据以往教学经验,结合初学者学习的实际情况,以进程同步中“读者-写者”为例,探讨如何由浅入深、循序渐进地开展教学工作。
1问题描述“读者—写者”问题是现代操作系统中经典的进程同步互斥问题,在以C/S模式为代表的多进(线)程通信系统都可以作为该模型的不同表现形式,有着广泛的应用[1]。
该问题描述如下:一个数据文件或记录可被多个进程所共享,我们将其中只要求读该文件的进程称为读者,即“Reader进程”,其他进程称为写者,即“Writer进程”。
多个Reader进程和多个Writer进程在某个时间段内对该文件资源进行异步操作,也就是说允许多个进程同时读一个共享对象,但绝不允许一个Writer进程和其他Reader进程或Writer进程同时访问共享对象,因此,所谓“读者—写者问题”就是指必须保证一个Writer进程和其他进程(Writer进程和Reader进程)互斥地访问共享对象的同步问题[2]。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
学号:课程设计课程名称操作系统学院计算机科学与技术学院专业软件工程专业班级姓名指导教师2014——2015学年第1学期目录目录 ....................................................................................................................................... 错误!未定义书签。
1 设计概述 (3)1.1问题描述: (3)1.2问题解读及规则制定 (3)2课程设计目的及功能 (3)2.1 设计目的 (3)2.2 设计功能 (3)3模块介绍 (3)3.1函数原型 (3)3.2 PV操作代码 (4)4测试用例,运行结果与运行情况分析 (6)4.1测试用例 (6)4.2运行结果 (7)4.3运行情况分析 (9)5自我评价与总结 (9)6 参考文献 (10)7 附录:(完整代码) (10)实现读者写者(Reader-Writer Problem)问题1 设计概述1.1问题描述:通过研究Linux的线程机制和信号量实现读者写者(Reader-Writer)问题并发控制。
1.2问题解读及规则制定一个数据文件或记录可被多个进程所共享,我们将其中只要求读该文件的进程称为读者,其他进程称为写者.多个读者和多个写者进程在某个时间段内对该文件资源进行异步操作,也就是说允许多个进程同时读一个共享对象,但不允许一个写进程和其他读进程或写进程同时访问共享对象,因此,所谓"读者--写者问题"就是指必须保证一个写进程和其他进程(写进程或者读进程)互斥地访问共享对象的同步问题.两者的读写操作限制规则如下:(1)写--写互斥,即不允许多个写着同时对文件进行写操作(2)读--写互斥,即不允许读者和写者同时对文件分别进行读写操作(3)读—读允许,即允许多个读者同时对文件进行读操作2课程设计目的及功能2.1 设计目的通过实验模拟读者和写者之间的关系,了解并掌握他们之间的关系及其原理。
由此增加对进程同步的问题的了解。
具体如下:1)掌握基本的同步互斥算法,理解读者和写者模型2)了解多线程的并发执行机制,线程间的同步和互斥2.2 设计功能:利用模拟用信号量机制实现读者和写者问题:通过用户控制读进程和写进程,反应读者和写者问题中所涉及的进程的同步与互斥。
3模块介绍3.1函数原型读者和写者进程由11个函数组成,分别如下: (附件包含全部具体实现)void P_write(int);void write(int);void V_write(int);void P_radd(int);void radd(int);void P_read(int);void V_radd(int);void read(int);void P_rsub(int);void rsub(int);void V_read(int);void V_rsub(int);3.2 PV操作代码:模拟写者对Wmutex的P操作,同时为写者进程也作写的入口:void P_write(int i){Wmutex--;if(Wmutex<0){w_wait[-Wmutex-1]=i;}elsewrite(i);}模拟写者对Wmutex的V操作,写操作完成的时候调用:void V_write(int i){w[i]=0;Wmutex++;if(Wmutex<=0){int k,j;if((w_wait[0]>=0)&&(w_wait[0]<w_num)){j=w_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];write(j);}else{j=r_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];V_radd(j);}}}模拟读之前对Rmutex的P操作,同时也作为读者进程的入口:void P_radd(int i) {Rmutex--;if(Rmutex<0){r_wait[-Rmutex]=i;}elseradd(i);}模拟读者对Wmutex的P操作:void P_read(int i){Wmutex--;if(Wmutex<0){w_wait[-Wmutex-1]=10;r_wait[0]=i;}elseV_radd(i);}模拟读之前对Rmutex的V操作:void V_radd(int i){Rmutex++;if(Rmutex<=0){int k,j;j=r_wait[0];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];radd(j);}read(i);}模拟读之后对Rmutex的P操作,读操作完成的时候调用:void P_rsub(int i){r[i]=0;Rmutex--;rsub(i);}模拟读者对Wmutex的V操作:void V_read(int i) {Wmutex++;if(Wmutex<=0){int k,j;if((w_wait[0]>=0)&&(w_wait[0]<w_num)){j=w_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];write(j);}else{j=r_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];V_radd(j);}}V_rsub(i);}模拟读之后对Rmutex的V操作:void V_rsub(int i){Rmutex++;}4测试用例,运行结果与运行情况分析4.1测试用例测试用例如下:1、输入写者个数:42、输入读者个数:23、写者1申请写操作,此时状态:写者1正在写4、读者1申请读操作,此时状态:写着1正在写,读者1等待6、写者1完成写操作,此时状态:读者1正在读7、读者2申请读操作,此时状态:读者1正在读,读着2正在读8、写者3申请写操作,此时状态:读者1正在读,读者2正在读,写着3等待9、读者1完成读操作,此时状态:读者2正在读,写着3等待10、读者2完成读操作,此时状态:写者3正在写11、写者2申请写操作,此时状态:写者3正在写,写者2等待12、写者3完成写操作,此时状态:写者2正在写13、写者2完成写操作,此时状态:无读无写14、写者4申请写操作,此时状态:写者4正在写15、读者1申请读操作,此时状态:写着4正在写,读者1等待16、读者2申请读操作,此时状态:写着1正在写,读者1等待,读者2等待17、写者4完成写操作,此时状态:读者1正在读,读者2正在读18、结束4.2运行结果运行结果如图:4.3运行情况分析当有读者对文件读时,写操作等待,读操作执行当有写者对文件写时,读操作等待,写操作等待完全符合限制规则及实际应用5自我评价与总结本次设计中,用C++编程模拟了用信号量机制实现读者和写者问题。
总的来说,通过本次设计收获很大。
读者和写者问题,一直认为这些东西很简单,但是具体编程实现其模拟并不容易。
虽然这还不算真正的实践,但通过这次设计,向实践靠近了一步。
更加深刻的理解了操作系统中这些理论知识的意义。
同时也让我温习以前所学习的高级语言。
6 参考文献[1] 报刊《计算机教育》文章编号1672-5913(2011)22-0056-03,《操作系统课程之“读者-写着”问题教学探讨》[2] 严蔚敏,吴伟民著,数据结构(c++版)北京:清华大学出版社,20077 附录:(完整代码)#include<iostream>int r_num;//读者个数int w_num;//写者个数int Wmutex=1;//表示允许写或允许读int readCount=0;//表示正在读的进程数int Rmutex=1;//表示对Rcount的互斥操作int r[10]={0,0,0,0,0,0,0,0,0,0};//表示读者的状态,1表示正在读int w[10]={0,0,0,0,0,0,0,0,0,0};//表示写者的状态,1表示正在写int w_wait[11]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};//表示等待队列,0-9表示写者,10时需引入读者的等待队列,-1表示空int r_wait[11]={-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};//读者的等待队列,0-9表示对应的读者,-1为空void P_write(int);//模拟写者对Wmutex的P操作,同时也作为写者进程的入口void write(int);//开始写操作void V_write(int);//模拟写者对Wmutex的V操作,写操作完成的时候调用void P_radd(int);//模拟读之前对Rmutex的P操作,同时也作为读者进程的入口void radd(int);//readCount加1void P_read(int);//模拟读者对Wmutex的P操作void V_radd(int);//模拟读之前对Rmutex的V操作void read(int);//读操作void P_rsub(int);//模拟读之后对Rmutex的P操作,读操作完成的时候调用void rsub(int);//readCount减1void V_read(int);//模拟读者对Wmutex的V操作void V_rsub(int);//模拟读之后对Rmutex的V操作void P_write(int i){Wmutex--;if(Wmutex<0) //表示如果Wmutex<0,则该写者进入等待队列{w_wait[-Wmutex-1]=i;}elsewrite(i);}void write(int i){w[i]=1;}void V_write(int i){w[i]=0;Wmutex++;if(Wmutex<=0) // 表示如果Wmutex<=0,则从等待队列中选择写者或读者进行操作{int k,j;if((w_wait[0]>=0)&&(w_wait[0]<w_num)){j=w_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];write(j);}else{j=r_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];V_radd(j);}}}void P_radd(int i) {Rmutex--;if(Rmutex<0) // 表示如果Rmutex<0,则进入等待队列{r_wait[-Rmutex]=i;}elseradd(i);}void radd(int i){readCount++;if(readCount==1)P_read(i);elseV_radd(i);}void P_read(int i){Wmutex--;if(Wmutex<0) // 表示如果Wmutex<0,则进入等待队列{w_wait[-Wmutex-1]=10;r_wait[0]=i;}elseV_radd(i);}void V_radd(int i){Rmutex++;if(Rmutex<=0) //表示如果Rmutex<=0,则从等待队列中选择读者进入readCount的临界区{int k,j;j=r_wait[0];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];radd(j);}read(i);}void read(int i){r[i]=1;}void P_rsub(int i){r[i]=0;Rmutex--;rsub(i);}void rsub(int i){readCount--;if(readCount==0)V_read(i);elseV_rsub(i);}void V_read(int i) {Wmutex++;if(Wmutex<=0) //表示如果Wmutex<=0,则从等待队列中选择写者或读者进行操作{int k,j;if((w_wait[0]>=0)&&(w_wait[0]<w_num)){j=w_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];write(j);}else{j=r_wait[0];for(k=0;k<w_num;k++) w_wait[k]=w_wait[k+1];for(k=0;k<r_num;k++) r_wait[k]=r_wait[k+1];V_radd(j);}}V_rsub(i);}void V_rsub(int i){Rmutex++;}int main(){using namespace std;cout<<"请输入写者个数(1到10):";cin>>w_num;while(w_num<1||w_num>10){cout<<"输入有误,请重新输入写者个数(1到10):";cin>>w_num;}//完成对写者个数的输入cout<<"请输入读者个数(1到10):";cin>>r_num;while(r_num<1||r_num>10){cout<<"输入有误,请重新输入读者个数(1到10):";cin>>r_num;}//完成对读者个数的输入int x,k,j,a[20];while(1){cout<<"----------------------------------------------------------------------"<<endl;for(k=0;k<20;k++) a[k]=0;cout<<"Wmutex="<<Wmutex<<"readCount="<<readCount<<"Rmutex="<<Rmutex<<endl;for(k=0;k<w_num;k++){if(w[k]==1)cout<<"-------写者"<<(k+1)<<"正在写"<<endl;}for(k=0;k<r_num;k++){if(r[k]==1)cout<<"-------读者"<<(k+1)<<"正在读"<<endl;}if(w_wait[0]==-1) cout<<"等待队列中无对象"<<endl;else{cout<<"等待队列中有:";for(k=0;k<w_num;k++){if(w_wait[k]==10)for(j=0;j<5;j++){if(r_wait[j]!=-1)cout<<"-->"<<"读者"<<(r_wait[j]+1);}if((w_wait[k]>=0)&&(w_wait[k]<w_num))cout<<"-->"<<"写者"<<(w_wait[k]+1);}cout<<endl;}for(k=0;k<w_num;k++){x=0;for(j=0;j<w_num;j++){if(k==w_wait[j]){a[k]=1;x=1;}}if(x==1) continue;cout<<"("<<(k+1)<<")写者"<<(k+1);if(w[k]==0) cout<<"申请";else cout<<"完成";}for(k=0;k<r_num;k++){x=0;for(j=0;j<r_num;j++){if(k==r_wait[j]){a[k+w_num]=1;x=1;}}if(x==1) continue;cout<<"("<<(k+1+w_num)<<")读者"<<(k+1);if(r[k]==0) cout<<"申请";else cout<<"完成";}cout<<"("<<(w_num+r_num+1)<<")结束"<<endl;cout<<"请输入选项序号:";cin>>x;while(x<1||x>(w_num+r_num+1)||a[x-1]==1){if(a[x-1]==1) cout<<"该对象已在等待队列中,请重新输入:";else cout<<"输入有误,请重新输入:";cin>>x;}for(k=0;k<w_num;k++){if(x==(k+1)){if(w[k]==0) P_write(k);else V_write(k);break;}}for(k=0;k<r_num;k++){if(x==(k+1+w_num)){if(r[k]==0) P_radd(k);else P_rsub(k);break;}}if(x==(w_num+r_num+1)) return 0;}}。