读者写者问题写者优先代码
操作系统——读者-写者问题的解决方法
操作系统——读者-写者问题的解决⽅法问题描述不允许Write进程和Read进程或其他Write进程同时访问⽂件,Read进程可以和其他Read进程同时访问。
分为三种类型。
读者优先要求:1.多个读者可以同时访问⽂件2.同⼀时间只允许⼀个写者访问⽂件3.读者和写者进程互斥解决⽅法:⽤⼀个readcounter记录是第⼏个读者在读,如果是第⼀个读者,则不能让写者写,需要⼀个锁。
因为readcounter是临界资源,也需要⼀个互斥量。
semaphore rc_mutex = 1, wmutex = 1;readcounter = 0;void writer{do{wait(wmutex);//writesignal(wmutex);}while(TRUE);}void reader{do{wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);// readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}写者优先要求:1.读者写者互斥2.写者读者同时等待时,所有等待的写者优先,等所有写者结束后,读者才能读3.没有写者时,读者能同时读4.写者到来时,不会终⽌已经进⾏的读者操作解决⽅法:semaphore wc_mutex = 1, prior = 1; //写者计数器,优先信号量readcounter = 0, writercounter = 0;void writer{do{wait(wc_mutex); //申请更改wc的权限if(writercounter == 0) //如果是第⼀个写者,就申请优先权限wait(prior);writercounter ++;signal(wc_mutex);wait(wmutex);//writesignal(wmutex);wait(wc_mutex);writercounter --;if(!writercounter)signal(prior); //当最后⼀个写者操作完成后,释放优先级权限 signal(wc_mutex);}while(TRUE);}void reader{do{wait(prior); //先申请优先级权限,如果前⾯还有写者就等待wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);signal(prior); //释放优先级权限// readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}读写均等semaphore prior = 1; //读者和写者都等待在⼀个队列上,实现读写均等readcounter = 0, writercounter = 0;void writer{do{wait(prior);wait(wmutex);//writesignal(wmutex);signal(prior);}while(TRUE);}void reader{do{wait(prior);wait(rc_mutex);if(readcounter == 0) wait(wmutex);readcounter ++;signal(rc_mutex);signal(prior);//readwait(rc_mutex);readcounter --;if(!readcounter) signal(wmutex);signal(rc_mutex);}while(TRUE);}有错误请指出!。
北理工操作系统实验二读者写者问题
本科实验报告实验名称:操作系统原理实验(读者写者问题)课程名称:操作系统原理实验时间:2015.10.30 任课教师:王耀威实验地点:10#102实验教师:苏京霞实验类型: 原理验证□综合设计□自主创新学生姓名:孙嘉明学号/班级:1120121474/05611202 组号:学院:信息与电子学院同组搭档:专业:信息对抗技术成绩:实验二:读者写者问题一、实验目的1.通过编写和调试程序以加深对进程、线程管理方案的理解;2.熟悉Windows多线程程序设计方法;二、实验要求在Windows环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先)1)写-写互斥:不能有两个写者同时进行写操作2)读-写互斥:不能同时有一个线程在读,而另一个线程在写。
3)读-读允许:可以有一个或多个读者在读。
读者优先的附加限制:如果读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
测试数据文件包括 n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每行测试数据包括四个字段,每个字段间用空格分隔。
第1个字段为正整数,表示线程的序号。
第2个字段表示线程的角色,R表示读者,W表示写者。
第3个字段为一个正数,表示读写开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的读写申请。
第4个字段为一个正数,表示读写操作的延迟时间。
当线程读写申请成功后,开始对共享资源进行读写操作,该操作持续相应时间后结束,释放该资源。
下面是一个测试数据文件的例子(在记事本手工录入数据):1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 3三、实验环境硬件设备:个人计算机。
读者-写者问题解答
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)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
读者写者问题实验报告
读者写者问题实验报告引言读者写者问题是计算机科学中经典的同步问题之一,它涉及多线程编程中的资源竞争与同步机制。
通过对读者写者问题的研究,我们可以深入理解线程同步的重要性,并掌握解决并发编程中可能出现的竞争条件和死锁等问题的方法。
在本实验中,我们将设计并实现一个简单的读者写者问题的解决方案,并通过模拟多个读者和写者的并发访问来验证方案的正确性和效果。
问题描述读者写者问题可描述为:有一共享资源(如文件、数据库等),读者可同时访问共享资源进行读取操作,但写者在进行写入操作时,不可同时被其他任何读者或写者访问。
读者和写者的并发访问需要由线程同步机制来保证共享资源的一致性和完整性。
实验设计与实现为了解决读者写者问题,我们需要考虑以下几个关键点:1. 共享资源的访问控制我们可以使用互斥量(Mutex)来实现对共享资源的访问控制。
当一个线程访问共享资源时,它需要先获得互斥量的锁,如果锁已被其他线程占用,则线程进入等待状态,直到锁可用。
一旦线程完成对共享资源的访问,它将释放锁,以便其他线程继续访问。
2. 读者与写者的优先级在读者写者问题中,我们往往需要设定某个优先级规则,以确定读者和写者之间的调度顺序。
一种常见的策略是给予写者优先级,即当一个写者在等待访问共享资源时,其他读者都必须等待。
这样做是为了避免写者长时间等待,以免造成饥饿问题。
3. 记录读者和写者的数量为了控制读者和写者的并发访问,我们需要记录当前同时访问共享资源的读者和写者的数量。
我们可以使用整数变量来记录读者和写者的数量,并通过信号量来保证对这些计数变量的互斥访问。
4. 同步机制的设计在实现读者写者问题的解决方案时,我们需要考虑如何合理地使用互斥量和信号量,并结合优先级规则来实现读者和写者的同步。
这需要通过仔细的设计和调试来确保解决方案的正确性。
实验结果与分析我们基于上述设计实现了一个读者写者问题的解决方案,并进行了多次仿真实验。
实验环境•操作系统:Windows 10•编程语言:C++•编译器:GCC实验步骤1.编写读者和写者线程的代码,其中涉及到对共享资源的读取和写入操作,以及对计数变量和互斥量的访问操作。
操作系统例题汇总
1.2例题精选例1.1如何理解虚拟机的概念?解:一台仅靠由硬件组成的计算机一般被称为裸机,不易使用。
操作系统为用户使用计算机提供了许多服务,从而把一台难于使用的裸机改造成了功能更强大、使用更方便的计算机系统,这种计算机系统称为虚拟机。
所谓虚拟,是指把一个物理上的实体变为若干个逻辑上的对应物。
前者是实际存在的,而后者是虚的,只是用户的一种感觉。
在单CPU的计算机系统中能同时运行多道程序,好像每个程序都独享一个CPU,这就是虚拟。
在构造操作系统时,把操作系统分成若干层,每层完成特定的功能,从而形成一个虚拟机。
下层的虚拟机为上层的虚拟机提供服务,这样逐次扩充以完成操作系统的功能。
讨论“虚拟”的概念体现在操作系统的方方面面。
例如,虚拟存储器,使一台只有4MB 内存的计算机可以运行总容量远远超过4 MB的程序;虚拟外设,能够使多个用户同时访问该外设等。
例1.2什么是多道程序设计,它的主要优点是什么?解: 所谓多道程序设计是指把一个以上的程序存放在内存中,并且同时处于运行状态,这些程序共享CPU和其他计算机资源。
其主要优点是:(1)CPU的利用率高:在单道程序环境下,程序独占计算机资源,当程序等待I/O操作时CPU空闲,造成CPU资源的浪费。
在多道程序环境下,多个程序共享计算机资源,当某个程序等待I/O操作时,CPU可以执行其他程序,这大大地提高了CPU的利用率。
(2)设备利用率高:在多道程序环境下,内存和外设也由多个程序共享,无疑也会提高内存和外设的利用率。
(3)系统吞吐量大:在多道程序环境下,资源的利用率大幅度提高,减少了程序的等待时间,提高了系统的吞吐量。
讨论多道程序在计算机中并发地运行是现代计算机系统的重要特征。
早期的单道批处理系统与人工操作相比自动化程度大大提高,但系统中仍有较多的空闲资源,系统的性能较差。
多遭批处理系统虽有很多优点,但这种系统交互能力差,作业的平均周转时间长。
多道程序处理系统要解决的主要问题是,如何使多个程序合理、有序地共事处理机、内存、外设等资源。
读写者问题
设计一读者写者问题实习环境:系统为Windows XP + VC 6.0一、实验目的:1、加深对进程概念的理解,明确进程和程序的区别,进一步认识并发执行的实质;2、理解和运用信号量、PV原语、进程间的同步互斥关系等基本知识。
二、设计要求在Windows XP下创建一个控制台进程,该进程应包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
3)读-读互斥,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有另一个写者在等待访问共享资源,则该读者必须等到没有写者出于等待状态后才能开始读操作。
测试文件格式说明,下面是一个测试数据文件的例子:1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 36 R 15 47 R 15 4三、设计说明1、读者优先指除非有写者在写文件,否则读者不需要等待。
所以可以用一个整形变量readnum记录当前的读者数目,用于确定是否需要唤醒正在等待的写者进程(当readnum==读者人数时,表明所有的读者读完,需要唤醒写者等待队列中的第一个写者)。
每一个读者开始读文件时,必须修改readnum变量。
因此需要一个互斥对象rnum[]来实现对全局变量readnum修改时的互斥。
另外,为了实现写写互斥,需要增加一个临界区对象wstate。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读写互斥,当readnum=2时(即第一个读者到来时),读者进程也必须申请临界区对象的所有权。
读者写者问题写者优先参考答案完整版
读者写者问题写者优先参考答案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)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
读者_写者问题的写者优先算法_符广全
收稿日期:2003-03-13作者简介:符广全(1966)),男,山东费县人,临沂师范学院讲师.读者-写者问题的写者优先算法符广全(临沂师范学院计算机与信息科学系,山东临沂276005)摘 要:分析了操作系统中读者-写者这个经典进程同步问题,对读者优先的算法加以改进,探讨了用信号量实现的写者优先的算法.关键词:信号量;互斥;同步;算法中图分类号:TP316 文献标识码:A 文章编号:1009-6051(2003)06-0135-02并发是现代操作系统的重要特征,进程的并发大大提高了系统效率,但也带来了不确定因素.因此,并发系统中处理好进程的互斥与同步至关重要.信号量机制是解决进程互斥与同步问题的重要工具,其应用很多而又复杂、常易出错,是操作系统原理学习中的重点与难点之一.信号量(semaphore)是荷兰计算机科学家Dijkstra 在1965年提出的一个同步机制,对信号量只能进行Wai t(S)、Signal(S)两个原语操作.信号量及Wait(S)、Si gnal(S)原语描述如下:type Semaphore=recordvalue:integer; L:pointer to PCB; end Wai t(S):S.value:=S.value-1; if S.value<0then beginInsert(C ALLER,S.L); Block(CALLER); endSignal(S):S.value:=S.value+1;if S.value<=0 then beginRemove(S.L,id); Wakeup(id); end其中Insert 、Block 、Remove 、Wakeup 均是系统提供的过程.读者-写者问题是一个用信号量实现的经典进程同步问题.在系统中,一个数据集(如文件或记录)被几个并发进程共享,其中有些进程要求读数据集,而另一些进程要求写或修改数据集.我们把只要求读的进程称为/读者0,其他进程称为/写者0,把此类问题称为/读者-写者0问题(Reader -Writers Problem).在这类问题中,我们允许多个读者同时读此数据集,但绝不允许一个写者和其他进程(读者或写者)同时访问此数据集,因为这将违反Bernstein 条件,破坏数据的完整性、正确性.解决此问题的最简单的方法是:当没有写进程正在访问共享数据集时,读进程可以进入访问,否则必须等待.操作系统的教材中一般都给出了不考虑写者优先的共享算法.在这种算法中,只要有读者不断到来,写者就要持久地等待,直到所有的读者都读完且没有新的读者到来时写者才能写数据集,是一种读者优先的算法.在此我们要对此算法改进,探讨一种实现写者优先的算法.在这个算法中,我们要实现的目标是:首先,要让读者与写者之间以及写者与写者之间要互斥地访问数据集,其次,在无写进程到来时各读者可同时访问数据集;在读者和写者都等待时访问时写者优先.我们将用两个不同的互斥信号量分别实现读者与写者间的互斥及各写者进程间的互斥:以互斥信号量Wmutex 实现各写者间的互斥,用互斥信号量Rmutex 实现各读者与写者间的互斥;设置两个整型变量Wcount 和Rcount 分别记录等待的写者数和正在读的读者数,因Wcount 、Rcount 都是共享变量,因此还要设置两个互斥信号量Mut1和Mut2以实现进程对这两个变量的互斥访问.用信号量机制实现的写者优先的算法如下:Var Mut1,Mut2,Wmu tex ,Rmutex:Semaphore;Rcount,Wcount:integer;第25卷 第6期临沂师范学院学报2003年12月Vol.25No.6Journal of Linyi Teachers .College Dec.2003Mut1:=Mut2:=Wmu tex:=Rmutex:=1; Rcount:=Wcount:=0;beginparbeginwriteri:beginWai t(Mut1);Wcount:=Wcount+1;If Wcount=1then Wait(Rmutex);Signal(Mut1);Wai t(Wmutex);写数据集;Wai t(Mut1);Wcount:=Wcount-1;If Wcount=0then Si gnal(Rmutex);Signal(Wmutex);Signal(Mut1);end Readeri:beginWait(Mu t1);Signal(Mut1);Wait(Mu t2);Rcount:=Rcount+1;If Rcount=1then Wait(Rmutex);Signal(Mut2);读数据集;Wait(Mu t2);Rcount:=Rcount-1;If Rcount=0then Signal(Rmutex);Signal(Mut2);endcoendend正访问者等待者(a)W1R1R2W2W3R3(b)R1W1R2R3W2W3图1正访问者与等待者次序算法分析:假设有诸多读者R1、R2、R3,及诸多写者W1、W2、W3,都要访问数据集,对以下几种情况下的优先、互斥情况分析如下:(1)当写者先到达进入数据集访问,其后到达的次序如图1(a)所示.因第1个写者W1访问数据集前要执行Wait(Rmutex),第1个读者R1等待在信号量Rmutex上,其他的读者等待在信号量Mut2上;第2、第3写者W2、W3等待在信号量Wmutex上,Wcount=3.W1写完后唤醒写者W2、W3,写者得以先于读者访问;最后的写者访问完成后唤醒第1个读者R1,R1唤醒R2后去访问数据集,随后R3被唤醒,R2、R3可与R1同时访问数据集.(2)当读者正访问数据集,又有诸多读者到来而无写者到来时诸读者可共同读数据集.(3)当读者正访问数据集,又有诸多读者和写者到来时(如图1(b)所示),写者能优先于诸读者访问数据集.此时,第1个写者W1等待在信号量Rmutex上,这时的第二、第三读者R2、R3不能进入临界区与R1共同访问数据集,而是等待在信号量Mut1上,第2、第3写者W2、W3也等待在信号量Mut1上;一旦R1完成后,唤醒第1个写者W1去访问数据集,W1访问数据集之前它将唤醒R2,继而R3、W2、W3会被唤醒,R2会重新被阻塞在信号量Rmutex上,R3被阻塞在信号量Mut2上,W2、W3会重新被阻塞在信号量Wmutex上;第1个写者W1访问完后,先唤醒写者W2、W3,最后一个写者完成后才唤醒读者R2、R3,因此,写者W2、W3会优先于读者R2、R3去访问数据集.需要说明的是,进程并发是系统中常见而且复杂的问题,信号量在进程的互斥、同步等方面有广泛的应用,但实现的方法也并不仅限于信号量机制.用信号量解决读者-写者问题,实现写者优先的算法不止一种,在此仅作抛砖引玉,与读者共商榷.参考文献:[1]汤子瀛,杨成忠,哲凤屏.计算机操作系统[M].西安:电子科技大学出版社,1996.[2]屠祁,屠立德.操作系统基础.北京:清华大学出版社,2000.Writer Priority Calculation of the Reader-Writer ProblemFU Guang-quan(Department of Computer and Information Science,Linyi Teachers.College,Linyi Shandong276005,China)Abstract:Not only the classic process synchronization)))Reader-Writer Problem is analyzed,but also the method to improve Reader Priority calcula tion is provided in this article.At the sa me time,the realization of Writer Priority calculation by using semaphore is also discussed.Key words:semaphore;mutual repellency;synchronization;calculation136临沂师范学院学报第25卷。
操作系统之读者与写者问题(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. 简介读者写者问题是指多个线程(读者线程和写者线程)同时访问共享资源(如文件、数据库等)时可能发生的同步问题。
当多个线程同时读取共享资源时,不会产生冲突,但是当一个线程将共享资源写入时,其他线程不能读取或写入相同的资源,否则可能引发数据不一致的问题。
因此,需要一种合理的调度算法来解决读者写者问题。
其中,写者优先算法是一种常用的调度算法,它保证当有写者等待时,任何新到达的读者都必须等待。
只有当没有写者在等待时,读者才能获得对共享资源的访问权限。
本文将详细介绍写者优先算法的实现。
2. 写者优先算法实现原理写者优先算法的目标是尽快处理写者线程的请求,以保证共享资源的可用性和数据的一致性。
在写者优先算法中,当有写者线程请求访问共享资源时,读者线程需要等待,直到没有写者线程在等待为止。
这样可以保证写者线程尽快获得对资源的访问权限,以便进行写入操作。
具体实现写者优先算法的方法可以通过使用信号量和互斥锁来实现。
其中,互斥锁用于保证在任意时刻只能有一个线程访问共享资源,而信号量则用于控制写者线程和读者线程的访问权限。
3. 写者优先算法的实现步骤下面是使用写者优先算法解决读者写者问题的实现步骤:3.1 初始化信号量和互斥锁首先,需要初始化两个信号量和一个互斥锁,分别用于控制读者线程的访问权限、写者线程的访问权限和互斥访问共享资源。
这可以通过如下代码实现:mutex = Semaphore(1) # 互斥锁,用于控制对共享资源的互斥访问reader_count = Semaphore(1) # 读者数量,用于控制读者线程的访问权限writer_count = Semaphore(1) # 写者数量,用于控制写者线程的访问权限3.2 编写读者线程代码读者线程的代码如下所示:def reader():# 读者线程的入口函数while True:writer_count.acquire() # 获取写者数量的访问权限reader_count.acquire() # 获取读者数量的访问权限# 读者线程访问共享资源reader_count.release() # 释放读者数量的访问权限writer_count.release() # 释放写者数量的访问权限3.3 编写写者线程代码写者线程的代码如下所示:def writer():# 写者线程的入口函数while True:writer_count.acquire() # 获取写者数量的访问权限reader_count.acquire() # 获取读者数量的访问权限mutex.acquire() # 获取互斥访问共享资源的权限# 写者线程访问共享资源mutex.release() # 释放互斥访问共享资源的权限reader_count.release() # 释放读者数量的访问权限writer_count.release() # 释放写者数量的访问权限3.4 启动线程最后,需要创建并启动多个读者线程和写者线程,以测试写者优先算法的实现。
读者-写者问题代码解释
读者-写者问题有同学反映“读者-写者问题”的代码比较难理解。
主要是因为Windows提供了一种互斥机制称为“Critical Section”,中文翻译为“临界区”,这个名字具有迷惑性,因为,它容易与我们课本上讲的“临界区”的概念混淆。
课本上临界区指“对临界资源进行访问的代码”;而这种称为“Critical Section”互斥机制,并不是这个意思,而是访问临界区之前的一种加锁机制,与Mutex 信号量的作用类似,只是“Critical Section”互斥机制只能在同一进程内部各个线程间使用,而Mutex互斥机制是可以跨进程使用的。
为帮助大家更容易理解读者-写者的代码,下面的代码用Mutex互斥机制替换了“Critical Section”互斥机制,并添加了部分注释,并用蓝色标注,其原理都是一样的。
#include "windows.h"#include "process.h"#include <conio.h>#include <stdlib.h>#include <fstream.h>#include <io.h>#include <string.h>#include <stdio.h>#define READER 'R' // 读者#define WRITER 'W' // 写者#define INTE_PER_SEC 1000 // 每秒时钟中断数目#define MAX_THREAD_NUM 64 // 最大线程数目#define MAX_FILE_NUM 32 // 最大数据文件数目#define MAX_STR_LEN 32 // 字符串长度volatile int readcount = 0; // 读者数目HANDLE RP_Write;struct ThreadInfo // 定义线程数据结构{int serial; // 线程序号char entity; // 线程类别(判断是读者线程还是写者线程)double delay; // 线程延迟double persist; // 线程读写操作持续时间};/////////////////////////////////////////////////////////////////////////// 读者优先——读者线程/// p:读者线程信息unsigned int __stdcall RP_ReaderThread(void *p){// 互斥变量HANDLE h_Mutex;h_Mutex = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");DWORD wait_for_mutex; //等待互斥变量所有权DWORD m_delay; //延迟时间DWORD m_persist; //读文件持续时间int m_serial; //线程序号//从参数中获得信息m_serial = ((ThreadInfo *)(p))->serial;m_delay = (DWORD)(((ThreadInfo *)(p))->delay*INTE_PER_SEC);m_persist = (DWORD)(((ThreadInfo*)(p))->persist*INTE_PER_SEC);Sleep (m_delay) ; //延迟等待printf("Reader thread %d sents the reading require......\n",m_serial);//等待互斥信号,保证对readcount的访问、修改互斥wait_for_mutex = WaitForSingleObject(h_Mutex,-1);// 读者数目增加readcount++;if(readcount ==1){//这是第一个读者,第二个读者到来时,readcount为2,if的条件不满足,不会进入if语句内部执行//这是第一个读者,如果此刻没有写者正在写,则RP_Write信号量状态为可用(未占用),那它就必须先占用(锁定)RP_Write信号量,这就实现了读-写互斥//如果此刻有写者正在写,则RP_Write信号量被写者占用(锁定),读者想对RP_Write加锁就会阻塞在此,等待RP_Write信号量释放后,才能继续运行WaitForSingleObject(RP_Write, INFINITE);}ReleaseMutex(h_Mutex) ; //释放互斥信号// 读文件printf("Reader thread %d begins to read file.\n",m_serial);Sleep(m_persist) ;// 退出线程printf("Reader thread %d finished reading file.\n",m_serial);//等待互斥信号,保证对readcount的访问、修改互斥wait_for_mutex = WaitForSingleObject(h_Mutex,-1) ;//读者数目减少readcount-- ;if(readcount == 0){//如果所有读者读完,则释放RP_Write信号量;此刻若有写者正在等待(处于阻塞状态),将(自动)唤醒写者ReleaseMutex(RP_Write);}ReleaseMutex(h_Mutex) ; //释放互斥信号return 0;}////////////////////////////////////////////////////////////////////////// 读者优先——写者线程// p:写者线程信息unsigned int __stdcall RP_WriterThread(void* p){DWORD m_delay; //延迟时间DWORD m_persist; //写文件持续时间int m_serial; //线程序号//从参数中获得信息m_serial = ((ThreadInfo *)(p))->serial;m_delay = (DWORD)(((ThreadInfo *)(p))->delay*INTE_PER_SEC) ;m_persist = (DWORD)(((ThreadInfo *)(p))->persist*INTE_PER_SEC) ;Sleep (m_delay); //延迟等待printf("Writer thread %d sents the writing require.\n",m_serial);// 写者在进行写数据之前,必须确定没有其它写者正在写,也没有其它读者在读,// 通过RP_Write互斥量实现,若有其它写者正在写或其它读者在读,则该写者调用“WaitForSingleObject(RP_Write, INFINITE);”后将阻塞在此// 等待RP_Write信号量释放后,才能够继续向下执行。
读者写者问题-写者优先参考答案
读者写者问题-写者优先参考答案【写者优先】在读者、写者问题中,如果总有读者进程进行读操作,会造成写者进程永远都不能进行写操作(读者优先),即所谓的写者饿死现象。
给出读者、写者问题的另一个解决方案:即保证当有一个写者进程想写时,不允许读者进程再进入,直到写者写完为止,即写者优先。
让我们先回顾读者写者问题[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,则迭代唤醒等待授权的读者;⏹读者到来,首先看授权标志,如果有授权标志,则继续,否则等待授权,即写者取消授权后,新来的读者不能申请缓冲区。
读者写者问题C源代码
读者——写者问题C++程序(原创作品)演示效果图:程序完整代码:#include <windows.h>#include <iostream.h>#include <fstream.h>#include <string.h>#include<string>#include<stdlib.h>//包含清屏头文件//全局变量int empty=1;//信号量int wrIn=1;//信号量int max;int temp[30];int *wait,*next;int count=0;//记录已经完成操作的线程数int waitSemapore;int type;//类型记录int writc=1;int readc=1;void reader()/////////////////////////////////////////////////////读者函数开始{empty--;//P操作改变信号量cout<<"读者获得资源"<<"(";SYSTEMTIME sys;GetLocalTime(&sys);//输出系统时间cout<<"系统时间:"<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wSecond<<":"<<sys.wMilliseconds<<")"<<e ndl;cout<<endl<<"*"<<"读者正在进行读操作..."<<endl;//empty++;//信号量count++;}/////////////////////////////////////////////////////////读者函数结尾void writer()//////////////////////////////////////////////////写者函数开始{empty--;//P操作改变信号量wrIn--;//P操作改变信号量cout << " 写者"<<writc<<"获得资源" <<"(";SYSTEMTIME sys;GetLocalTime(&sys);//输出系统时间cout<<"系统时间:"<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wSecond<<":"<<sys.wMilliseconds<<")"<<endl;cout<<"请输入线程要写入的内容,以/结尾"<<endl;char ch='a';ofstream outfile("f.txt",ios::out|ios::app);if(!outfile){cerr<<"open file error!"<<endl;abort();}while(ch!='/'){ cin>>ch;outfile<<ch;}cout<<endl<<"*" <<"写者"<<writc<<"正在进行写操作.." << endl;outfile.close();count++;//wrIn++;//V操作改变信号量//empty++;//V操作改变信号量}//////////////////////////////////////////////////////////////写者函数结尾void codeIn()/////////////////////////////////////////////////////////////////输入界面{int ru;cout<<"请输入你要创建多少个线程:"<<endl;cin>>max;for(int i=0;i<max;i++){cout<<"你所要创建的第"<<i+1<<"个线程类型为:1.读者 2.写者"<<endl; cin>>ru;///////////////if(ru==1||ru==2)temp[i]=ru;elsecout<<"输入有误!请重新输入"<<endl;/////////////判断错误if(i==max-1)//录入最后一个线程类型操作{//system("cls");//清屏HANDLE hOut;hOut = GetStdHandle(STD_OUTPUT_HANDLE); //设置输出字体颜色red SetConsoleTextAttribute(hOut,FOREGROUND_RED |FOREGROUND_INTENSITY);cout<<endl<<"输入完毕!"<<endl;hOut = GetStdHandle(STD_OUTPUT_HANDLE); //设置输出字体背景SetConsoleTextAttribute(hOut,BACKGROUND_GREEN |BACKGROUND_INTENSITY); for(int j=0;j<max;j++)//////////////////输出录入结果{cout<<"线程"<<j+1<<"为:";if(temp[j]==1)cout<<"读者"<<endl;else cout<<"写者"<<endl;}///////////////////////////////输出录入结果cout<<"下面将进行动态演示:"<<endl<<endl;system("pause");cout<<endl;}//录入最后一个线程类型操作}//录入界面结束}}/////////////////////////////////////////////////////////codeIn()int main()/////////////////////////////////////////////////主函数{codeIn();//录入界面wait=&temp[0];while(wait<&temp[max]&&count<max){waitSemapore=1;next=wait;while(*next==1||*next==2)//线程调用算法{if(*next==1)//reader{if(empty==1||(empty==0&&wrIn==1&&*wait!=2))//体现写者优先{reader();//调用读者函数type=1;}else{cout<<"["<<"读者此时正在等待资源"<<"]"<<endl;//Sleep(5000);////////////////////////////////////////////////////////////////////////////////////////////sleep() if(waitSemapore==1){wait=next;//////////this reader is waiting,locate it.waitSemapore--;}}}else//writer{if(empty==1){writer();//调用写者函数type=2;}else{cout<<"["<<"写者此时正在等待资源"<<"]"<<endl;//Sleep(5000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()if(waitSemapore==1)///////////this writer is waiting,find it's location.{wait=next;waitSemapore--;}}}//writer is endnext++;}//1while()if(type==1){cout<<"~"<<"读者"<<readc<<"读完毕,释放资源"<<endl;readc++;empty++;//读者用的,但是为了在输出时演示出运行状态,不得不将其放在此处Sleep(3000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()cout<<endl;}elseif(type==2){cout<<"~"<<"写者"<<writc<<"写完毕,释放资源" << endl;writc++;wrIn++;//V操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放在此处empty++;//V操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放在此处Sleep(3000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()cout<<endl;}}//2while()return 0;}/////////////////////////////////////////////////////主函数结束。
读者写者问题_写者优先参考答案
}
}
void writer() /*写者进程*/
{
if(Rcount>0)
authFlag=0;
P(Wmutex);
......;
write; /* 执行写操作 */
......;
P(Wmutex);
P(Amutex)
while(waitAuthCount>0){
v(mutexAuth);
waitAuthCou
【vc++代码】
// testsemaphore.cpp : Defines the entry point for the console application.
// by西南大学计算机科学系周竹荣
//
#include"stdafx.h"
#include"windows.h"
Rmutex=CreateSemaphore(NULL,1,1,NULL);
Authmutex=CreateSemaphore(NULL,1,1,NULL);
Amutex=CreateSemaphore(NULL,1,1,NULL);
while(1){
Sleep(100);
srand((unsigned)time(NULL));
允许任意多的读进程同时读;
一次只允许一个写进程进行写操作;
如果有一个写进程正在进行写操作,禁止任何读进程进行读操作。
为了解决该问题,我们只需解决“写者与写者”和“写者与第一个读者”的互斥问题即
可,为此我们引入一个互斥信号量Wmutex,为了记录谁是第一个读者,我们用一个共享整
型变量Rcount 作一个计数器。而在解决问题的过程中,由于我们使用了共享变量Rcount,
北理工操作系统读者-写者问题实验报告
实验二:读者写者问题班级:学号:姓名:实验二:读者写者问题一、实验目的1.通过编写和调试程序以加深对进程、线程管理方案的理解;2.熟悉Windows多线程程序设计方法;二、实验要求在Windows环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先)1)写-写互斥:不能有两个写者同时进行写操作2)读-写互斥:不能同时有一个线程在读,而另一个线程在写。
3)读-读允许:可以有一个或多个读者在读。
读者优先的附加限制:如果读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
运行结果显示要求:要求在每个线程创建、发出读写申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
测试数据文件包括n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。
每行测试数据包括四个字段,每个字段间用空格分隔。
第1个字段为正整数,表示线程的序号。
第2个字段表示线程的角色,R表示读者,W表示写者。
第3个字段为一个正数,表示读写开始时间:线程创建后,延迟相应时间(单位为秒)后发出对共享资源的读写申请。
第4个字段为一个正数,表示读写操作的延迟时间。
当线程读写申请成功后,开始对共享资源进行读写操作,该操作持续相应时间后结束,释放该资源。
下面是一个测试数据文件的例子(在记事本手工录入数据):1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 3三、实验环境硬件设备:个人计算机。
系统软件:windows操作系统,Visual C++6.0编译环境。
四、实验原理所谓读者写者问题,可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书,并且,读者比写者优先,也就是说,读者和写者同时提出请求时,读者优先。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
读者写者问题-写者优先代码
#include<stdio.h>
#include<stdlib.h>
int rcount=0;//正在读的读者数量
int wcount=0;//写者队列中等待写操作的写者数量
int rid=0;//读进程号
int wid=0;//写进程号
int w=1;//读写互斥信号量
char temp[300] = {'\0'};
int sign; //标识temp空的信号量0表示temp空
void WFwakeup();
void RFwakeup();
struct rqueue{//读者等待队列
int readers[200];
int index;
}rq;
struct wqueue{//写者等待队列
int writers[200];
int index;
}wq;
void read(){
int i = 0;
rid++;
if(rcount == 0){//当前没有读进程在读可能有写进程在写可能CPU空闲if(w==1) {//如果CPU空闲,读者拿到CPU
w--;// 相当于一个P操作
rcount++;
if(temp[0] == '\0'){
sign = 0;
rq.readers[rq.index++]=rid;//将读者进程加入等待队列
WFwakeup();
return;
}//if
printf("读者%d正在读\n",rid);
for(i = 0;i < 300;i++){//读取temp内容即写者写的内容
if(temp[i] == '\0'){
printf("\n");
return;
}//if
printf("%c",temp[i]);
}//for
}//if
else{//写者线程正在执行
printf("有写者在写不能读!\n");
rq.readers[rq.index++]=rid;//将读者进程加入等待队列
}//else
}//if
else{//rcount !=1 则知道当前已经有读者在读,读读不互斥,则这个读者可以直接进来了读
printf("读者%d正在读\n",rid);
for(i = 0;i < 300;i++){
if(temp[i] == '\0'){
printf("\n");
return;
}
printf("%c",temp[i]);
}//for
}//else
}
//***************************写进程写操作
void write(){
wid++;
if(w == 0){
if(rcount != 0 ){//有读者进程在执行
printf("有读者在读不能写!\n");
wq.writers[wq.index++]=wid;//将写者进程加入等待队列
wcount++;
return;
}
if(rcount == 0 ){//rcount == 0则当前无读者,但w = 0,所以有写者在写
printf("有写者在写不能写!\n");
wq.writers[wq.index++]=wid;//将写者进程加入等待队列
wcount++;
return;
}
}
if(w == 1){
w--;
printf("写者%d正在写\n请输入要写的内容",wid);
scanf("%s",temp);
//while
}//if
}
//******************************************写者优先唤醒
void WFwakeup(){
int i = 0;
int j = 0;
int m;
m = rq.index;
//n = wq.index;
if(rcount == 0){//当前无读进程,是写者在写--》停止运行写进程
bool writer_wait=false;
w=1;
printf("写者已经写完\n");
sign = 1;//temp中已经有内容要置1
for(i=0;i<=wq.index;i++){// index为当前写者队列中的等待进程数
if(wq.writers[i]!=0){
writer_wait=true; //确实有写者在等待
printf("等待的写者%d正在写\n 请输入要写的内容\n",wq.writers[i]); w = 0;
scanf("%s",temp);
wq.writers[i]=0;
wcount--;
break;
}
}
if(!writer_wait){//没有写者等待,看是
否有读者等待
for(int i=0;i<=m;i++){//检查写者等待队列
if(rq.readers[i]!=0){
w = 0;
printf("等待的读者%d正在读\n",rq.readers[i]);
for(j = 0;j < 300;j++){
if(temp[j] == '\0'){
printf("\n");
rq.index--;
break;
}//if
printf("%c",temp[j]);
}//for
rq.readers[i]=0;
rcount++;
}//if
}//for
}//if
// return;
}//if
else{//rcount != 0读者正在读,stop读此时若有等待必为写者
rcount=0;
w = 1;
printf("读者已经读完\n");
for(int i=0;i<=wq.index;i++){// 检查写者等待队列
if(wq.writers[i]!=0){
w = 0;
printf("等待的写者%d正在写\n请输入要写入的内容",wq.writers[i]);
scanf("%s",temp);
wq.writers[i]=0;
wcount--;
break;
}//if
}//for
}
}
void main(){
char i;
printf("=====================\n 0.显示主菜单\n 1.创建读者进程\n 2.创建写者进程\n 3.结束当前执行的进程\n 4.退出程序\n=====================\n");
do{
printf("当前队列中有读者:%d个写者:%d个\n",rq.index,wcount); scanf("%s",&i);
switch(i){
case '0':
printf("=====================\n 0.显示主菜单\n 1.创建读者进程\n 2.创建写者进程\n 3.结束当前执行的进程\n 4.退出程序\n=====================\n"); break;
case '1':
read();
break;
case '2':
write();
break;
case '3':
WFwakeup();
break;
case '4':
exit(0);
default:
printf("输入错误请重新输入\n"); }
}while(true);
}。