北理工操作系统实验二读者写者问题
操作系统课程设计报告——读者写者问题

操作系统课程设计课题:读者写者问题姓名:赫前进班级: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)问题

学号:课程设计课程名称操作系统学院计算机科学与技术学院专业软件工程班级姓名指导教师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进程才能进入临界区写。 本设计方案就是通过利用记录型信号量对读者写者问题的解决过程 进行模拟演示,形象地阐述记录型信号量机制的工作原理。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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语言对进程进行控制和调度,通过实验了解了互斥量、信号量、事件等数据结构的使用,完成了读者写者的编程。