北理工操作系统实验二读者写者问题

合集下载

操作系统课程设计报告——读者写者问题

操作系统课程设计报告——读者写者问题

操作系统课程设计课题:读者写者问题姓名:赫前进班级:1020552学号102055211指导教师:叶瑶提交时间:2012/12/30(一)实验目的1.进一步理解“临界资源”的概念;2.把握在多个进程并发执行过程中对临界资源访问时的必要约束条件;3.理解操作系统原理中“互斥”和“同步”的涵义。

(二)实验内容利用程序设计语言编程,模拟并发执行进程的同步与互斥(要求:进程数目不少于3 个)。

(三)、程序分析读者写者问题的定义如下:有一个许多进程共享的数据区,这个数据区可以是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)和一些只往数据区写数据的进程(Writer),此外还需要满足以下条件:(1)任意多个读进程可以同时读这个文件;(2)一次只有一个写进程可以往文件中写;(3)如果一个写进程正在进行操作,禁止任何读进程度文件。

实验要求用信号量来实现读者写者问题的调度算法。

实验提供了signal类,该类通过P( )、V( )两个方法实现了P、V原语的功能。

实验的任务是修改Creat_Writer()添加写者进程,Creat_Reader()创建读者进程。

Reader_goon()读者进程运行函数。

读优先:要求指一个读者试图进行读操作时,如果这时正有其他读者在进行操作,他可直接开始读操作,而不需要等待。

读者优先的附加限制:如果一个读者申请进行读操作时已有另一读者正在进行读操作,则该读者可直接开始读操作。

写优先:一个读者试图进行读操作时,如果有其他写者在等待进行写操作或正在进行写操作,他要等待该写者完成写操作后才开始读操作。

写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

在Windows 7 环境下,创建一个控制台进程,此进程包含n 个线程。

用这n 个线程来表示n 个读者或写者。

每个线程按相应测试数据文件(格式见下)的要求进行读写操作。

操作系统——读者-写者问题的解决方法

操作系统——读者-写者问题的解决方法

操作系统——读者-写者问题的解决⽅法问题描述不允许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);}有错误请指出!。

操作系统课设: 实现读者写者(Reader-Writer Problem)问题

操作系统课设: 实现读者写者(Reader-Writer Problem)问题

学号:课程设计课程名称操作系统学院计算机科学与技术学院专业软件工程班级姓名指导教师2014——2015学年第1学期1《操作系统原理》课程设计指导书课程编号:课程名称:操作系统/Operating System周数/学分:1周/1学分先修课程:高级语言程序设计、汇编语言、数据结构、计算机组成原理适用专业:计算机科学与技术、软件工程开课学院、系或教研室:计算机科学与技术学院一、课程设计的目的通过对操作系统内核实现代码的阅读、修改、设计,理解和掌握复杂的操作系统的工作原理。

二、课程设计的内容和要求1.系统调用学习在Linux中产生一个系统调用以及怎样通过往Linux内核中增加一个新函数从而在该内核空间中实现对用户空间的读写。

这个函数的功能是返回当前的系统时间。

实验条件要求:每人一台Linux主机且有超级用户权限。

2.内核定时器通过研究内核的时间管理算法学习内核源代码。

然后应用这些知识并且使用“信号”建立一种用户空间机制来测量一个多线程程序的执行时间。

实验条件要求:每人一台Linux主机且有超级用户权限。

3.实现生产者消费者(Bounded – Buffer Problem)问题通过研究Linux的线程机制和信号量实现生产者消费者(Bounded Buffer)问题的并发控制。

实验条件要求:每人一台与Linux主机联网的Windows主机,普通用户权限。

4.实现读者写者(Reader-Writer Problem)问题通过研究Linux的线程机制和信号量实现读者写者(Reader-Writer)问题并发控制。

实验条件要求:每人一台与Linux主机联网的Windows主机,普通用户权限。

三、课程设计进度安排四、课程设计说明书与图纸要求应包含如下内容:1.设计题目与要求2.总的设计思想及系统平台、语言、工具等。

3.数据结构与模块说明(功能与流程图)4.源程序5.运行结果与运行情况6.调试记录7.自我评析和总结五、课程设计评分标准注:优(90-100分)、良(80-89分)、中(70-79分)、及格(60-69分)、60分以下为不及格。

操作系统实验-读者写者问题

操作系统实验-读者写者问题

《计算机操作系统》实验报告题目读者写者问题学院(部)信息学院专业计算机科学与技术班级、学生姓名学号指导教师(签字)一、《二、问题描述一个数据文件或者记录,可以被多个进程共享,我们把只要求读该文件的进程称为“Reader进程”,其他进程则称为“Writer进程”。

允许多个进程同时读一个共享对象,因为读操作不会是数据文件混乱。

但不允许一个Writer进程和其他Reader进程或者Writer进程同时访问共享对象,因为这种访问将会引起混乱。

所谓“读者——写着问题(Reader—Writer Problem)”是指保证一个Writer进程必须与其他进程互斥地访问共享对象的同步问题三、解决问题为实现Reader与Writer进程间在读或写是的互斥而设置了一个互斥的信号量Wmutex。

另外,在设置一个整型变量Readcount表示正在读的进程数目。

由于只要有一个Reader进程在读,便不允许Writer去写。

因此,仅当Readercount=0时,表示尚无Reader进程在读时,Reader进程才需要进行Wait(wmutex)操作。

若Wait(Wmutex)操作成功,Reader 进程便可去读,相应地,做Readcount+1操作。

同理,仅当Reader进程在执行了Readercount-1操作后其值为0时,才执行Signal(Wmutex)操作,以便让Writer进程写。

又因为Readercount是一个可被多个Reader 进程访问的临界资源,因此也应该为它设置一个互斥信号量rmutex。

四、代码实现1、读者优先#include<iostream>#include<>using namespace std;CRITICAL_SECTION rmutex,wmutex;int wr;$int readernum;DWORD WINAPI reader(LPVOID IpParamter){cout<<"读者申请\n";wr++;EnterCriticalSection(&rmutex);if(readernum==0)EnterCriticalSection(&wmutex);readernum++;cout<<"读者进入成功正在读取\n";LeaveCriticalSection(&rmutex);Sleep(2000);—EnterCriticalSection(&rmutex);readernum--;cout<<"读者退出\n";wr--;if(readernum==0)LeaveCriticalSection(&wmutex);LeaveCriticalSection(&rmutex);return 0;}DWORD WINAPI writer(LPVOID PM){cout<<"写者申请\n";&while(wr!=0){}EnterCriticalSection(&wmutex);cout<<"写者已进入正在写入\n";Sleep(500);cout<<"写者退出\n";LeaveCriticalSection(&wmutex);return 0;}int main(){readernum=0;#wr=0;InitializeCriticalSection(&rmutex);InitializeCriticalSection(&wmutex);HANDLE hr[5];//定义读者线程HANDLE hw[5];//定义写者线程//int thnum;int drn=0; //输入的读者个数int dwn=0; //输入的写者个数cout<<"输入读者写者线程 1代表读者 2代表写者 0代表结束"<<endl;int th[10];int num=0;^cin>>th[num];while(th[num]){if(th[num]==1){drn++;}if(th[num]==2){dwn++;}num++;cin>>th[num];}&int hr1=0,hw1=0;for(int j=0;j!=num;j++){if(th[j]==1){hr[hr1]=CreateThread(NULL,0,reader,NULL,0,NULL);hr1++;}if(th[j]==2){hw[hw1]=CreateThread(NULL,0,writer,NULL,0,NULL);hw1++;}}>WaitForMultipleObjects(drn, hr, TRUE, INFINITE);WaitForMultipleObjects(dwn, hw, TRUE, INFINITE);for(int i=0;i!=drn;i++){CloseHandle(hr[i]);}for(int i=0;i!=dwn;i++){CloseHandle(hw[i]);}DeleteCriticalSection(&rmutex);DeleteCriticalSection(&wmutex);return 0;(}2、写者优先#include<iostream>#include<>using namespace std;CRITICAL_SECTION rmutex,wmutex;int ww;int readernum;DWORD WINAPI reader(LPVOID IpParamter){cout<<"读者申请\n";!while(ww!=0){}EnterCriticalSection(&rmutex);if(readernum==0){EnterCriticalSection(&wmutex);}cout<<"读者进入成功正在读取\n";readernum++;LeaveCriticalSection(&rmutex);Sleep(2000);EnterCriticalSection(&rmutex);-readernum--;if(readernum==0)LeaveCriticalSection(&wmutex);cout<<"读者退出\n";LeaveCriticalSection(&rmutex);return 0;}DWORD WINAPI writer(LPVOID PM){ww++;cout<<"写者申请\n";EnterCriticalSection(&wmutex);{cout<<"写者已进入正在写入\n";Sleep(1000);cout<<"写者退出\n";ww--;LeaveCriticalSection(&wmutex);return 0;}int main(){readernum=0;ww=0;InitializeCriticalSection(&rmutex);|InitializeCriticalSection(&wmutex);HANDLE hr[5];//定义读者线程HANDLE hw[5];//定义写者线程int drn=0; //输入的读者个数int dwn=0; //输入的写者个数cout<<"输入读者写者线程 1代表读者 2代表写者 0代表结束"<<endl;int th[10];int num=0;cin>>th[num];while(th[num]){if(th[num]==1){、drn++;}if(th[num]==2){dwn++;}num++;cin>>th[num];}int hr1=0,hw1=0;for(int j=0;j!=num;j++){if(th[j]==1){》hr[hr1]=CreateThread(NULL,0,reader,NULL,0,NULL);Sleep(10);hr1++;}if(th[j]==2){hw[hw1]=CreateThread(NULL,0,writer,NULL,0,NULL);Sleep(10);hw1++;}}WaitForMultipleObjects(drn, hr, TRUE, INFINITE);*WaitForMultipleObjects(dwn, hw, TRUE, INFINITE);for(int i=0;i!=drn;i++){CloseHandle(hr[i]);}for(int i=0;i!=dwn;i++){CloseHandle(hw[i]);}DeleteCriticalSection(&rmutex);DeleteCriticalSection(&wmutex);return 0;}3、执行结果读者优先在读者优先中先两个读者申请,再一个写者申请,再有两个读者申请。

读者写者问题实验报告

读者写者问题实验报告

读者写者问题实验报告1. 引言读者写者问题是操作系统中的经典同步问题,用于研究多线程环境下对共享资源的访问和保护。

在该问题中,有多个读者和写者同时对一个共享资源进行操作,需要保证并发访问时的正确性和效率。

通过本实验,我们将探讨读者写者问题的解决方案,并比较不同算法的性能差异。

2. 实验目标本实验的主要目标是通过实现和比较不同的读者写者问题算法,深入了解并发访问的挑战和解决方案。

具体而言,我们将研究以下几个方面:•设计并实现读者写者问题的解决方案•比较不同算法的性能差异•分析可能的优化策略3. 实验方法我们将使用Python编程语言来实现读者写者问题的解决方案。

在实验过程中,我们将尝试以下几种常见的算法:3.1. 读者优先算法在读者优先算法中,当有读者在访问共享资源时,其他读者可以同时访问,但写者需要等待。

只有当所有读者完成访问后,写者才能获得访问权限。

3.2. 写者优先算法在写者优先算法中,当有写者在访问共享资源时,其他读者和写者都需要等待。

只有当写者完成访问后,其他读者或写者才能获得访问权限。

3.3. 公平算法在公平算法中,读者和写者的访问权限是公平的,先到先得。

无论读者还是写者,都需要按照到达的顺序依次获取访问权限。

4. 实验步骤下面是我们实施实验的具体步骤:4.1. 实现基本的读者写者问题解决方案我们首先实现基本的读者写者问题解决方案,包括读者和写者的线程逻辑和共享资源的访问控制。

我们将使用互斥锁和条件变量来保证并发访问的正确性。

4.2. 实现读者优先算法在已有的基本解决方案的基础上,我们实现读者优先算法。

我们将通过优化访问控制的逻辑来实现读者优先的特性。

4.3. 实现写者优先算法类似地,我们在基本解决方案的基础上实现写者优先算法。

我们将调整访问控制的逻辑,使得写者优先于其他读者和写者。

4.4. 实现公平算法最后,我们实现公平算法。

我们将结合队列和条件变量等技术来确保读者和写者的访问顺序是公平的。

读者-写者问题解答计算机操作系统实验报告指导资料

读者-写者问题解答计算机操作系统实验报告指导资料

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)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。

“读写平等”策略的“读者--写者”问题实验报告

“读写平等”策略的“读者--写者”问题实验报告

淮北师范大学程序设计课程设计采用“读写平等”策略的“读者--写者”问题学院计算机科学与技术专业计算机科学与技术(师范)学号 ***********学生姓名 ***指导教师姓名 ***2012年6月16 日一、设计目的与内容课程设计的目的:操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决问题的机会。

●进一步巩固和复习操作系统的基础知识。

●培养学生结构化程序、模块化程序设计的方法和能力。

●提高学生调试程序的技巧和软件设计的能力。

●提高学生分析问题、解决问题以及综合利用C语言进行程序设计的能力。

设计内容:用高级语言编写和调试一个采用“读写平等”策略的“读者—写者”问题的模拟程序。

设计的要求:1.读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入。

2.读者与写者均有两个以上,可在程序运行期间进行动态增加读者与写者。

3.可读取样例数据(要求存放在外部文件中),进行读者/写者、进入内存时间、读写时间的初始化。

4.要求将运行过程用可视化界面动态显示,可随时暂停,查看阅览室中读者/写者数目、读者等待队列、读写时间、等待时间。

5.读写策略:读写互斥、写写互斥、读写平等(严格按照读者与写者到达的顺序进入阅览室,有写着到达,则阻塞后续到达的读者;有读者到达,则阻塞后续到达的写者)。

有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间,甚至可以是一组处理器寄存器。

有一些只读取这个数据区的进程(reader)和一些只往数据区中写数据的进程(writer)。

以下假设共享数据区是文件。

这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。

这些条件具体来说就是:(1)任意多的读进程可以同时读这个文件;(2)一次只允许一个写进程往文件中写;(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;(4)写进程执行写操作前,应让已有的写者或读者全部退出。

操作系统读者写者实验报告

操作系统读者写者实验报告

g_hReadSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号 灯,当前可用的资源数为1,最大为100 g_hWriteSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号 灯,当前可用的资源数为1,最大为100 CreatePersonList(g_PersonLists); // Create All the reader and writers printf("Created all the reader and writer\n...\n"); g_CurrentTime = 0; while(true) { g_CurrentTime++; Sleep(300); // 300 ms printf("CurrentTime = %d\n",g_CurrentTime); if(finished) return 0; } // return 0; } void CreatePersonList(int *pPersonLists) { int i=0; int *pList = pPersonLists; bool Ret; while(pList[0] != END) { switch(pList[1]) { case R: Ret = CreateReader(pList[2],pList[3],pList[0]);//351,w452,523,654 break; case W: Ret = CreateWriter(pList[2],pList[3],pList[0]);
. Perform reader operation; Ssignal(L,1); Until false; End Writer :begin Repeat Swait(mx ,1,1,l,RN,0); Perform writer operation; Ssignal(mx,1); Until false; End Parend End 其中,Swait(mx,1,0)语句起着关作用,只要无Writer进程进入 些,mx=1,reader进程就都可以进入读。但是要一旦有Writer进程进入 写时,其MX=0,则任何reader进程就都无法进入读。Swait(mx ,1,1,l,RN,0)语句表示仅当既无Write进程在写(mx=1),又无reader进程 在读(L=RN)时,writer进程才能进入临界区写。 本设计方案就是通过利用记录型信号量对读者写者问题的解决过程 进行模拟演示,形象地阐述记录型信号量机制的工作原理。

读者写者实验报告

读者写者实验报告

操作系统原理实验报告实验名称:操作系统姓名: XXX学号: xxxxxxxxxx班级: xxx指导老师: xxx一、实验内容在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。

用这n个线程来表示n个读者或写者。

每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。

用信号量机制分别实现读者优先和写者优先的读者-写者问题。

读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。

2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。

,3)读-读允许,即可以有一个或多个读者在读。

读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。

写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。

二、实验目的在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。

用这n 个线程来表示n个读者或写者。

每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。

用信号量机制分别实现读者优先和写者优先的读者-写者问题。

三、实验原理1).读者优先读者优先指的是除非有写者在写文件,否则读者不需要等待。

所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=O时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。

每一个读者开始读文件时,必须修改read_count变量。

因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。

另外,为了实现写-写互斥,需要增加一个临界区对象write。

操作系统读者写者实验报告

操作系统读者写者实验报告

操作系统读者写者实验报告一、实验目的通过实验理解读者写者问题的实现原理,掌握相关的同步机制,实现读者写者问题的经典解法,并对比不同解法的优缺点。

二、实验原理1.读者写者问题读者写者问题是指在多个线程同时读写一个共享数据的情况下可能出现的问题。

其问题的核心在于多个读线程可以同时读,但只能有一个写线程能够写,并且在写操作过程中不能有任何的读操作。

2.互斥与同步为了解决读者写者问题,在多线程并发读写共享数据时,需要使用互斥与同步机制来保证数据的完整性和一致性。

-互斥:通过锁机制来保证只允许一个线程进入临界区,其他线程需要等待锁的释放。

-同步:通过信号量等机制来保证线程按照一定顺序执行。

三、实验步骤本次实验中将实现两个版本的读者写者问题解决方案:一是使用互斥锁和条件变量,二是使用信号量。

1.使用互斥锁和条件变量(1)定义全局变量和互斥锁:共享数据、读者数目、互斥锁、写者条件变量、读者条件变量。

(2)初始化互斥锁和条件变量。

(3)写者线程的实现:获取互斥锁,判断当前是否有读者或写者,如果有则等待条件变量,然后进行写操作,释放互斥锁。

(4)读者线程的实现:获取互斥锁,判断是否有写者,如果有则等待条件变量,否则增加读者数目并释放互斥锁,进行读操作。

(5)测试程序的运行并输出结果。

2.使用信号量(1)定义全局变量和信号量:共享数据、读者信号量、写者信号量、用于保护读者数目和写者数目的互斥信号量。

(2)初始化信号量和互斥信号量。

(3)写者线程的实现:首先获取写者互斥信号量,然后获取写者信号量,进行写操作,释放写者信号量和写者互斥信号量。

(4)读者线程的实现:首先获取读者互斥信号量,然后增加读者数目,如果是第一个读者则获取写者信号量,然后进行读操作,释放读者信号量和读者互斥信号量,如果是最后一个读者则释放写者信号量。

(5)测试程序的运行并输出结果。

四、实验结果与分析通过对比两种解决方案,可以得出以下结论:1.使用互斥锁和条件变量的解决方案相对较为简单,但可能存在饥饿问题,即可能会导致一些线程一直无法访问共享资源。

操作系统读者写者实验报告

操作系统读者写者实验报告

《操作系统原理》课程设计课程设计起止时间:2009年11月30日至12月11日指导教师:成绩:课程设计成绩评定表一.设计说明(四号,宋体,加粗)通过学习操作系统,与之前的语句基础相结合,用C语言来编写读者写着问题。

读者写者问题(read—write problem)是一个经典的并发程序设计问题。

有两组并发进程:读者和写者,共享一个问题F,要求:(1)允许多个读者可同时对之执行读操作;(2)只允许一个写者往文件中写信息;(3)任一写者在完成写操作之前不允许其他读者或者写者工作;(4)写者执行写操作前,应让已有的写者和读者全部退出。

二.工作原理(四号,宋体,加粗)读者和写者问题是典型是经典的进程同步问题,进程同步任务是使并发的诸进程之间有效的共享资源,相互合作,从而保证程序的可再现性。

在读者—写者问题中,允许多个读者同时读一个数据对象,因为读文件不会使数据发生混乱,但绝不允许一个写者进程与其他读者进程或写者进程同时访问该数据对象。

文件是诸进程能互斥访问临界资源,读者进程和写者进程,写者进程和写者进程之间的互斥。

在读者进程中,可以有多个读者在读数据库,在读者进程的计数要互斥,以免发生错误,同时注意当第一个读者进程读时,一定要封锁写者进程。

当读者进程逐渐撤离时,也要针对计数变量进行互斥操作,若当前为最后一个读者进程时,读完后,则唤醒写者进程。

当写者进程在进行写操作时,可以封锁其他读者或写者进程,当写操作完成时,唤醒其他读者或写者进程。

所以分析了以下4种可能发生的情况:第 1 种情况: 读者的优先权比写者高,而且,不用调配。

所有读者的优先权都比写者的优先权高,而且,不用调配。

一个读者需要等待的唯一情况是,一个写者已经占用了文件。

一个写者可以取得文件的条件是,没有一个读者处在等待状态或正在读文件。

允许读者们结盟,以便能长期占用文件,而禁止写者的写。

第 2 种情况: 在一个读者已经占有了文件的时候,全体读者的优先权才比写者高。

操作系统读者写者问题报告

操作系统读者写者问题报告

操作系统读者写者问题报告一、引言操作系统中的读者写者问题是一个经典的同步问题,它涉及多个进程对共享资源的访问,需要保证数据的正确性和一致性。

本报告将介绍读者写者问题的背景、定义、解决方法以及实现过程。

二、背景读者写者问题最早由Dijkstra在1965年提出,它是一个典型的并发控制问题。

在多进程环境下,当多个进程同时访问共享资源时,容易发生冲突和竞争条件。

读者写者问题就是其中比较常见和重要的一种。

三、定义读者写者问题是指有多个进程同时访问一个共享资源,其中有些进程只是读取该资源,而另一些进程则需要修改该资源。

为了保证数据的正确性和一致性,必须采取某种机制来控制这些进程对共享资源的访问。

四、解决方法1. 互斥锁:使用互斥锁来保证同一时间只有一个进程可以访问共享资源。

这种方法简单易行,但可能会导致饥饿现象。

2. 信号量:使用信号量来实现对共享资源的访问控制。

其中包括两个信号量:一个用于记录正在访问该资源的读者数量,另一个用于记录正在访问该资源的写者数量。

这种方法可以避免饥饿现象,但可能会导致死锁。

3. 读写锁:使用读写锁来实现对共享资源的访问控制。

读写锁包括两种类型:读锁和写锁。

多个进程可以同时获得读锁,但只有一个进程可以获得写锁。

这种方法可以提高并发性能,但实现较为复杂。

五、实现过程下面以信号量为例介绍如何实现读者写者问题:1. 定义两个全局变量readcount和writecount,分别表示正在访问该资源的读者数量和写者数量。

2. 定义两个信号量mutex和wrt,初始化为1。

3. 读者进程:a. P(mutex);b. readcount++;c. 如果readcount==1,则P(wrt);d. V(mutex);e. 读取共享资源;f. P(mutex);g. readcount--;h. 如果readcount==0,则V(wrt);i. V(mutex)。

4. 写者进程:a. P(wrt);b. 写入共享资源;c.V(wrt)。

读者写者实验报告

读者写者实验报告

操作系统原理实验报告实验名称:操作系统姓名: XXX学号: xxxxxxxxxx班级: xxx指导老师: xxx一、实验内容在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。

用这n个线程来表示n个读者或写者。

每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。

用信号量机制分别实现读者优先和写者优先的读者-写者问题。

读者-写者问题的读写操作限制(包括读者优先和写者优先):1)写-写互斥,即不能有两个写者同时进行写操作。

2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。

,3)读-读允许,即可以有一个或多个读者在读。

读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。

写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。

二、实验目的在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。

用这n 个线程来表示n个读者或写者。

每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。

用信号量机制分别实现读者优先和写者优先的读者-写者问题。

三、实验原理1).读者优先读者优先指的是除非有写者在写文件,否则读者不需要等待。

所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=O时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。

每一个读者开始读文件时,必须修改read_count变量。

因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。

另外,为了实现写-写互斥,需要增加一个临界区对象write。

读者写者问题-操作系统实验报告

读者写者问题-操作系统实验报告

实验内容1、定义一个数据缓存buffer 及用于实现同步互斥的信号量。

2、定义一个读者函数:● 当有写者在占用buffer 时,读者应该等待,直到写者不再使用该buffer 。

● 当有其他读者在占用buffer 时,读者可对buffer 进行读取操作。

● 当buffer 中有数据时,则从其中读取一个数据,并显示然后退出。

● 当buffer 中没有数据时,应等待,直到buffer 中有数据可读。

3、定义一个写者函数● 当有读者在占用buffer 时,写者应该等待,直到所有的读者都退出为止。

● 当有其他写者占用buffer 时,该写者应该等待,直到占用buffer 的写者退出为止。

● 当buffer 有空闲时,写者应该在buffer 中写入一个数据并退出。

● 当buffer 满时,写者应该等待,直到buffer 有空闲为止。

4、定义主函数,在其中可以任意创建读者与写者。

● 可根据用户输入创建读者或写者进程(线程)。

5、用户界面2. 写者: 开始读出的内容:1. 读者: 开始结束 21读者队列等待结束写出的内容: Hello world ! 结束实验当堂所要完成事情列表:1.调试程序使其在读者优先模式下可以运行并且能实现基本的功能得出正确的结果:能够实现读写互斥,写写互斥,读读不互斥,一个进程结束能够唤醒等待队列中的进程(先读者队列后写着队列)2.根据实验要求完善功能:由用户决定写者向缓冲区中写入的内容,读者能够读出并显示出来;当缓冲区中没有数据时,读者要等待,直到缓冲区中有数据才能读3.根据“读者优先”加以改变,增加一个“写者优先”模式,并且由用户来选择模式源代码:#include<stdio.h>#include<stdlib.h>int rcount=0;//正在读的读者数量int wcount=0;//写者队列中等待写操作的写者数量int read_id=0;//读进程号int write_id=0;//写进程号int w=1;//读写互斥信号量char temp[300] = {'\0'};int choice; //用户选择读者优先OR写者优先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 first(){ //初始化int i;rq.index = 0;wq.index = 0;for(i = 0;i<20;i++){rq.readers[i] = 0;wq.writers[i] = 0;}}*///*******************************************读进程读操作void read(){int i = 0;read_id++;if(rcount == 0){//当前没有读进程在读可能有写进程在写可能CPU空闲if(w==1) {//如果CPU空闲,读者拿到CPUw--;// 相当于一个P操作rcount++;if(temp[0] == '\0'){sign = 0;if(choice == 1){rq.readers[rq.index++]=read_id;//将读者进程加入等待队列RFwakeup();return;}else{rq.readers[rq.index++]=read_id;//将读者进程加入等待队列WFwakeup();return;}}//ifprintf("读者%d正在读\n",read_id);for(i = 0;i < 300;i++){//读取temp内容即写者写的内容if(temp[i] == '\0'){printf("\n");return;}//ifprintf("%c",temp[i]);}//for}//ifelse{//写者线程正在执行printf("!有写者在写不能读!\n");rq.readers[rq.index++]=read_id;//将读者进程加入等待队列}//else}//ifelse{//rcount !=1 则知道当前已经有读者在读,读读不互斥,则这个读者可以直接进来了读printf("读者%d正在读\n",read_id);for(i = 0;i < 300;i++){if(temp[i] == '\0'){printf("\n");return;}printf("%c",temp[i]);}//for}//else}//***************************写进程写操作void write(){write_id++;if(w == 0){if(rcount != 0 ){//有读者进程在执行printf("!有读者在读不能写!\n");wq.writers[wq.index++]=write_id;//将写者进程加入等待队列wcount++;return;}if(rcount == 0 ){//rcount == 0则当前无读者,但w = 0,所以有写者在写printf("!有写者在写不能写!\n");wq.writers[wq.index++]=write_id;//将写者进程加入等待队列wcount++;return;}}if(w == 1){w--;printf("写者%d正在写\n请输入要写的内容",write_id);scanf("%s",temp);//while}//if}//************************读者优先时唤醒进程void RFwakeup(){int i = 0;int j = 0;int m,n;m = rq.index;// n = wq.index;if(rcount == 0){//当前无读进程,是写者在写 --》停止运行写进程bool reader_wait=false;w=1;printf("写者已经写完\n");sign = 1;//temp中已经有内容要置1for(i=0;i<=m;i++){// i ndex为当前读者队列中的等待进程数if(rq.readers[i]!=0){reader_wait=true; //确实有读者在等待printf("等待的读者%d正在读\n",rq.readers[i]);w = 0;for(j = 0;j < 300;j++){if(temp[j] == '\0'){printf("\n");break;}//ifprintf("%c",temp[j]);}//forrq.readers[i]=0;rcount++;rq.index--;}//if}//forif(!reader_wait){//没有读者等待,看是否有写者等待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}//if// return;}//ifelse{//rcount != 0读者正在读,stop读此时若有等待必为写者rcount=0;w = 1;if(sign == 0){printf("缓冲区空等待写者\n");return;}else{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}}//else}//******************************************写者优先唤醒void WFwakeup(){int i = 0;int j = 0;int m,n;m = rq.index;//n = wq.index;if(rcount == 0){//当前无读进程,是写者在写 --》停止运行写进程bool writer_wait=false;w=1;printf("写者已经写完\n");sign = 1;//temp中已经有内容要置1for(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){//没有xie者等待,看是否有du者等待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;}//ifprintf("%c",temp[j]);}//forrq.readers[i]=0;rcount++;}//if}//for}//if// return;}//ifelse{//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 menu1(){char i;printf(" 1-创建读者进程\n 2-创建写者进程\n 3-结束当前执行的进程\n 4-退出程序\n");printf("*******************************************\n");do{printf("当前队列中有读者: %d个写者: %d个\n",rq.index,wcount);printf("*******************************************\n");printf(" ----->");scanf("%s",&i);switch(i){case '1':read();break;case '2':write();break;case '3':RFwakeup();break;case '4':exit(0);default:printf("输入错误请重新输入\n");}}while(true);}void menu2(){char i;printf(" 1-创建读者进程\n 2-创建写者进程\n 3-结束当前执行的进程\n 4-退出程序\n");printf("*******************************************\n");do{printf("当前队列中有读者: %d个写者: %d个\n",rq.index,wcount);printf("*******************************************\n");printf(" ----->");scanf("%s",&i);switch(i){case '1':read();break;case '2':write();break;case '3':WFwakeup();break;case '4':exit(0);default:printf("输入错误请重新输入\n");}}while(true);}void main(){printf("*************************************************** ***********************\n");printf(" 20092104实验一\n 1.读者优先\n 2.写者优先\n");scanf("%d",&choice);while(1){if(choice == 1)menu1();if(choice == 2)menu2();if(choice != 1 && choice != 2){printf("输入错误请重新输入\n");scanf("%d",&choice);}}}实验流程图:核心部分设计思路:分别用两个队列来存放等待的读者进程和写者进程,一个进程结束后就要将因他阻塞的进程唤醒,如果是读者优先,则先检查读者进程,如果发现读者进程不为空,就进行读操作,直到读者进程为空,才进行写操作;同理,如果是写者优先,则先检查写进程,如果发现写者进程不为空,就进行写操作,直到写者进程为空,才进行读操作。

读者写者问题实验报告

读者写者问题实验报告

读者写者问题实验报告1.实验目的:掌握读者写者问题的基本概念和操作实现方法。

2.实验原理:(1)读者写者问题:1.读者优先:若读者进程正在读文件,写者进程需等待。

2.写者优先:若写者进程正在写文件,读者进程需等待。

3.公平竞争:读写者进程均有机会访问文件。

(2)进程同步:1.信号量:能够同步进程的执行,性能较好。

2.互斥量:能够同步进程的执行,提供了更细粒度的控制。

3.条件变量:让进程能够进行相互之间的协作。

3.实验内容:(1)依照读者写者问题的操作实现方法,采用信号量机制,编写读者进程和写者进程。

(2)测试不同读者写者优先级下程序的执行情况。

4.实验步骤:(1)设计程序架构:1.使用信号量实现读者写者访问文件的同步操作;2.设计Readers和Writers两个类分别实现读者和写者进程的操作。

(2)实现程序:1.编写读者进程,在进程对文件进行读操作之前使用信号量P操作,读取完成后使用信号量V操作;2.编写写者进程,在进程对文件进行写操作之前使用信号量P操作,写入完成后使用信号量V操作;3.设计信号量的初始值,以实现不同读者写者优先级下程序的执行情况。

(3)测试程序:在有多个读者进程和多个写者进程的情况下,测试不同读者写者优先级下程序的执行情况。

5.实验结果:(1)读者优先:读者优先的情况下,不管读者进程和写者进程的数量如何设置,读者总是有后进先出的机会访问文件。

(2)写者优先:写者优先的情况下,不管读者进程和写者进程的数量如何设置,写者总是有先进先出的机会访问文件。

(3)公平竞争:公平竞争的情况下,读者或写者进程均有机会访问文件。

6.实验结论:(1)在实现读者写者问题的过程中,需要采用进程同步技术来确保进程之间的正确协作。

(2)信号量提供了一种较为有效的进程同步机制,能够满足读者写者问题的操作需求。

(3)采用不同的优先级设置,可以使读者写者进程之间实现不同的访问策略,进而实现不同的访问效果。

读者写者问题-写者优先参考答案

读者写者问题-写者优先参考答案

读者写者问题-写者优先参考答案【写者优先】在读者、写者问题中,如果总有读者进程进行读操作,会造成写者进程永远都不能进行写操作(读者优先),即所谓的写者饿死现象。

给出读者、写者问题的另一个解决方案:即保证当有一个写者进程想写时,不允许读者进程再进入,直到写者写完为止,即写者优先。

让我们先回顾读者写者问题[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,则迭代唤醒等待授权的读者;⏹读者到来,首先看授权标志,如果有授权标志,则继续,否则等待授权,即写者取消授权后,新来的读者不能申请缓冲区。

读者写者问题实验报告

读者写者问题实验报告
if(pPerson->m_nID == 4) finished = true; //所有的读写完成
ExitThread(0);
return 0;
}
DWORD WINAPI WriterProc(LPVOID lpParam)
{
Person *pPerson = (Person*)lpParam;
// wait for the start time
四、实验结果与数据处理
源代码
#include <windows.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#define MAX_PERSON 100
#define READER 0 //读者
当读者拥有临界区所有权时,写者阻塞在临界区对象write上.当写者拥有临界区所有权时,第一个读者判断完”read_count==1”后阻塞在write上,其余的读者由于等待对read_count的判断,阻塞在mutex上.
b)写者优先
写者优先与读者优先类似.不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作.为此应当添加一个整形变量write_count,用于记录正在等待的写者的数目,当write_count=0时,才可以释放等待的读者线程队列.
WaitForSingleObject(g_hReadSemaphore,INFINITE); if(g_NumOfReading ==0)

操作系统阅读者与写入者

操作系统阅读者与写入者

操作系统实验报告班级:电信1105学号:u201113208姓名:陈玉莲一.实验项目:阅读者和写入者问题二.实验目的针对阅读者和写入者问题中出现的问题,理解信号量的使用;理解源程序的算法,深刻理解阅读者和写入者权限的算法,以及相关窗口的操作;进一步加强对VC的应用能力。

三.实验内容1.问题描述有一个公用的数据集,有很多人需要访问,其中一些需要阅读其中的信息,一些需要修改其中的消息。

阅读者可以同时访问数据集,而写入者只能互斥的访问数据集,不能与任何的进程一起访问数据区。

2.程序运行说明1. 本程序主要用于说明阅读者写入者问题中的资源互斥访问的调动策略,并模仿其访问的过程。

采用书上的伪码编制而成,实际上采用的是读优先策略。

2. 在本程序中用于表现的图形界面说明:在程序编译运行后会出现中间一个大的圆圈表示公用的资源,上面一排五个矩形表示5个读者,下面的五个矩形表示五个写入者。

每个读者和写入者都有3种状态,休息,等待和操作(读入或者写入)分别用黑颜色,绿颜色,红颜色表示休息,等待和操作。

一旦操作者获得资源,可以进行读或者写,我们就划一条从操作者中心到资源中心的线,表示开始操作。

四.程序代码及分析1、伪代码:var mutex,wrt:Semaphore;readcount:integer;mutex:=wrt:=1; //定义初始信号量readcount:=0; //0位阅读者cobeginReaderi:beginP(mutex); //创造段,使以下操作不被打断readcount:=readcount+1; //等待阅读者加一if readcount=1 thenP(wrt); //禁止写入V(mutex);读数据集;P(mutex);readcount:=readcount-1; //等待阅读者减一if readcount=0 thenV(wrt); //开放写入V(mutex);EndWriteri:beginP(wrt);写数据集;V(wrt);end;coend2、代码分析:程序中,实现读者优先的原则,即当有读者等待时,优先使读者读消息,等到读者阅读完成后再进行写入操作(不可同时读出和写入,但可以同时多用户读出)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

本科实验报告实验名称:操作系统原理实验(读者写者问题)课程名称:操作系统原理实验时间: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三、实验环境硬件设备:个人计算机。

系统软件:windows操作系统,Visual C++6.0编译环境。

四、实验原理读者写者问题,可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书,并且,读者比写者优先,也就是说,读者和写者同时提出请求时,读者优先。

当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S来当前是否可操作。

信号量机制是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者则是这一机制的一个经典范例。

在程序文件根目录下创建一个thread.dat文件,存放读者写者信息,完成读者优先和写者优先的过程。

五、实验结果程序界面:使用的测试文件如下:1 R 3 52 W 4 53 R 5 24 R 6 55 W 5.1 3读者优先结果:写者优先结果:六、程序代码# include "windows.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 // 字符串长度int readcount = 0; // 读者数目int writecount = 0; // 写者数目CRITICAL_SECTION RP_Write; // 临界区CRITICAL_SECTION cs_Write;CRITICAL_SECTION cs_Read;struct ThreadInfo{int serial; // 线程序号char entity; // 线程类别(判断是读者线程还是写者线程) double delay; // 线程延迟double persist; // 线程读写操作持续时间} ;// 读者优先--读者线程// p: 读者线程信息void 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( "读者线程<%d> 发送读文件请求.\n" , m_serial) ;// 等待互斥信号,保证对readcount的访问、修改互斥wait_for_mutex = WaitForSingleObject (h_Mutex, -1) ;// 读者数目增加readcount ++;if (readcount == 1){// 第一个读者,等待资源EnterCriticalSection(&RP_Write) ;}ReleaseMutex(h_Mutex) ; // 释放互斥信号// 读文件printf( "读者线程<%d> 开始读文件.\n" , m_serial) ;Sleep(m_persist) ;// 退出线程printf("读者线程<%d> 读文件结束.\n" , m_serial) ;// 等待互斥信号,保证对readcount的访问、修改互斥wait_for_mutex = WaitForSingleObject(h_Mutex, -1) ;// 读者数目减少readcount --;if (readcount == 0){// 如果所有读者读完,唤醒写者LeaveCriticalSection(&RP_Write) ;}ReleaseMutex(h_Mutex) ; // 释放互斥信号}// 读者优先--写者线程// p: 写者线程信息void 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("写者线程<%d> 发送写文件请求.\n" , m_serial) ;// 等待资源EnterCriticalSection(&RP_Write);// 写文件printf( "写者线程<%d> 开始写文件.\n" , m_serial) ;Sleep(m_persist) ;// 退出线程printf("写者线程<%d> 写文件结束.\n" , m_serial) ;// 释放资源LeaveCriticalSection(&RP_Write) ;}// 读者优先处理函数// file: 文件名void ReaderPriority(char * file){DWORD n_thread = 0; // 线程数目DWORD thread_ID; // 线程IDDWORD wait_for_all; // 等待所有线程结束// 互斥对象HANDLE h_Mutex;h_Mutex = CreateMutex(NULL, FALSE, "mutex_for_readcount" ) ;// 线程对象的数组HANDLE h_Thread[ MAX_THREAD_NUM] ;ThreadInfo thread_info[MAX_THREAD_NUM] ;readcount = 0; // 初始化readcountInitializeCriticalSection(&RP_Write) ; // 初始化临界区ifstream inFile;inFile.open(file) ; // 打开文件printf("读者优先: \n \n" ) ;while (inFile){// 读入每一个读者、写者的信息inFile >> thread_info[n_thread].serial;inFile >> thread_info[n_thread].entity;inFile >> thread_info[n_thread].delay;inFile >> thread_info[n_thread ++ ].persist;inFile.get() ;}n_thread--;for (int i = 0; i < (int) (n_thread); i ++){if (thread_info[i].entity == READER || thread_info[i].entity == 'R' ){// 创建读者线程h_Thread[i] = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE) (RP_ReaderThread) ,&thread_info[i] , 0, &thread_ID) ;printf("读者线程<%d> 已创建.\n" , thread_info[i].serial) ;}else {// 创建写者线程h_Thread[i] = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE) (RP_WriterThread) ,&thread_info[i] , 0, &thread_ID) ;printf("写者线程<%d> 已创建.\n" , thread_info[i].serial) ;}}// 等待所有线程结束wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1) ;printf("所有读者写者均完成操作.\n" ) ;}// 写者优先--读者线程// p: 读者线程信息void WP_ReaderThread(void * p){// 互斥变量HANDLE h_Mutex1;h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex1" ) ; HANDLE h_Mutex2;h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex2" ) ;DWORD wait_for_mutex1; // 等待互斥变量所有权DWORD wait_for_mutex2;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("读者线程<%d> 发送读文件请求.\n" , m_serial) ;wait_for_mutex1 = WaitForSingleObject(h_Mutex1, -1) ;// 进入读者临界区EnterCriticalSection(&cs_Read) ;// 阻塞互斥对象mutex2,保证对readcount的访问、修改互斥wait_for_mutex2 = WaitForSingleObject(h_Mutex2, -1) ; // 修改读者数目readcount ++;if (readcount == 1){// 如果是第一个读者,等待写者写完EnterCriticalSection(&cs_Write) ;}ReleaseMutex(h_Mutex2) ; // 释放互斥信号mutex2// 让其他读者进入临界区LeaveCriticalSection(&cs_Read) ;ReleaseMutex(h_Mutex1) ;// 读文件printf("读者线程<%d> 开始读文件.\n" , m_serial) ;Sleep(m_persist) ;// 退出线程printf("读者线程<%d> 读文件结束.\n" , m_serial) ;// 阻塞互斥对象mutex2,保证对readcount的访问、修改互斥wait_for_mutex2 = WaitForSingleObject(h_Mutex2, -1) ;readcount -- ;if (readcount == 0){// 最后一个读者,唤醒写者LeaveCriticalSection(&cs_Write) ;}ReleaseMutex(h_Mutex2) ; // 释放互斥信号}// 写者优先--写者线程// p: 写者线程信息void WP_WriterThread(void * p){DWORD m_delay; // 延迟时间DWORD m_persist; // 写文件持续时间int m_serial; // 线程序号DWORD wait_for_mutex3;// 互斥对象HANDLE h_Mutex3;h_Mutex3 = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "mutex3" ) ;// 从参数中获得信息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("写者线程<%d> 发送写文件请求.\n" , m_serial) ;// 阻塞互斥对象mutex3, 保证对writecount的访问、修改互斥wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1) ;writecount ++ ; // 修改写者数目if (writecount == 1){// 第一个写者,等待读者读完EnterCriticalSection(&cs_Read) ;}ReleaseMutex(h_Mutex3) ;// 进入写者临界区EnterCriticalSection(&cs_Write) ;// 写文件printf("写者线程<%d> 开始写文件.\n" , m_serial) ;Sleep(m_persist) ;// 退出线程printf("写者线程<%d> 写文件结束.\n" , m_serial) ;// 离开临界区LeaveCriticalSection(&cs_Write) ;// 阻塞互斥对象mutex3,保证对writecount的访问、修改互斥wait_for_mutex3 = WaitForSingleObject(h_Mutex3, -1) ;writecount --;if (writecount == 0){// 写者写完,读者可以读LeaveCriticalSection(&cs_Read) ;}ReleaseMutex(h_Mutex3) ;}/// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /// 写者优先处理函数// file: 文件名void WriterPriority(char * file){DWORD n_thread = 0; // 线程数目DWORD thread_ID; // 线程IDDWORD wait_for_all; // 等待所有线程结束// 互斥对象HANDLE h_Mutex1;h_Mutex1 = CreateMutex(NULL, FALSE, "mutex1" ) ;HANDLE h_Mutex2;h_Mutex2 = CreateMutex(NULL, FALSE, "mutex2" ) ;HANDLE h_Mutex3;h_Mutex3 = CreateMutex(NULL, FALSE, "mutex3" ) ;// 线程对象HANDLE h_Thread[MAX_THREAD_NUM] ;ThreadInfo thread_info[MAX_THREAD_NUM] ;readcount = 0; // 初始化readcountwritecount = 0; // 初始化writecountInitializeCriticalSection(&cs_Write) ; // 初始化临界区InitializeCriticalSection(&cs_Read) ;ifstream inFile;inFile.open(file) ; // 打开文件printf("写者优先: \n \n" ) ;while (inFile){// 读入每一个读者、写者的信息inFile >> thread_info[n_thread].serial;inFile >> thread_info[n_thread].entity;inFile >> thread_info[n_thread].delay;inFile >> thread_info[n_thread ++].persist;inFile.get() ;}n_thread--;for (int i = 0; i < (int) (n_thread) ; i ++){if (thread_info[i].entity == READER || thread_info[i].entity == 'R' ){// 创建读者线程h_Thread[i] = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE) (WP_ReaderThread) ,&thread_info[i] , 0, &thread_ID) ;printf("读者线程<%d> 已创建.\n" , thread_info[i].serial) ;}else{// 创建写者线程h_Thread[i] = CreateThread(NULL, 0,(LPTHREAD_START_ROUTINE) (WP_WriterThread) ,&thread_info[i] , 0, &thread_ID) ;printf("写者线程<%d> 已创建.\n" , thread_info[i].serial) ;}}// 等待所有钱程结束wait_for_all = WaitForMultipleObjects(n_thread, h_Thread, TRUE, -1) ;printf("所有读者写者均完成操作.\n" ) ;}/// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /// 主函数int main(int argc, char * argv[]){char ch;while (true){// 打印提示信息printf( "------------------------------------------------\n" ) ;printf( " 请选择:\n " ) ;printf( " 1: 读者优先\n ");printf( " 2: 写者优先\n" ) ;printf( " 3: 退出程序\n" ) ;printf( "------------------------------------------------\n" ) ;printf( "请输出(1, 2 or 3) : " ) ;// 如果输入信息不正确,继续输入do {ch = (char) _getch() ;} while (ch != '1' && ch != '2' && ch != '3') ;system( "cls" ) ;// 选择3,返回if (ch == '3' )return 0;// 选择1, 读者优先else if (ch == '1')ReaderPriority( "thread.dat" ) ;// 选择2,写者优先elseWriterPriority( "thread.dat" ) ;// 结束printf( "\n按任意键继续: " ) ;_getch() ;system( "cls" ) ;}return 0;}七、心得体会通过这次实验,我学会了使用C语言对进程进行控制和调度,通过实验了解了互斥量、信号量、事件等数据结构的使用,完成了读者写者的编程。

相关文档
最新文档