操作系统OS报告读者与写者问题(进程同步问题)
读者-写者问题(Reader-Writer Problem)

学号:课程设计题目用多线程同步方法解决读者-写者问题(Reader-Writer Problem)学院计算机科学与技术学院专业软件工程班级姓名指导教师2010 年 6 月日目录目录 (1)课程设计任务书 (1)正文 (2)1.设计目的与要求 (2)1.1设计目的 (2)1.2设计要求 (2)2.设计思想及系统平台 (2)2.1设计思想 (2)2.2系统平台及使用语言 (3)3.详细算法描述 (3)4.源程序清单 (6)5.运行结果与运行情况 (9)6.调试过程 (11)7.总结 (12)本科生课程设计成绩评定表 (13)课程设计任务书学生姓名:专业班级:指导教师:工作单位:计算机科学与技术学院题目: 用多线程同步方法解决读者-写者问题(Reader-Writer Problem)初始条件:1.操作系统:Linux2.程序设计语言:C语言3.设有20个连续的存储单元,写入/读出的数据项按增序设定为1-20这20个字符。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.技术要求:1)为每个读者/写者产生一个线程,设计正确的同步算法2)每个读者/写者对该存储区进行操作后,即时显示该存储区的全部内容、当前指针位置和读者/写者线程的自定义标识符。
3)读者应有3个以上,写者应有有两个以上。
4)多个读者/写者之间须共享对存储区进行操作的函数代码。
2.设计说明书内容要求:1)设计题目与要求2)总的设计思想及系统平台、语言、工具等。
3)数据结构与模块说明(功能与流程图)4)给出用户名、源程序名、目标程序名和源程序及其运行结果。
(要注明存储各个程序及其运行结果的主机IP地址和目录。
)5)运行结果与运行情况(提示: (1)连续存储区可用数组实现。
(2)编译命令可用:cc -lpthread -o 目标文件名源文件名(3)多线程编程方法参见附件。
)3. 调试报告:1) 调试记录2)自我评析和总结上机时间安排:18周一~ 五08:0 -12:00指导教师签名:年月日系主任(或责任教师)签名:年月日正文1.设计目的与要求1.1设计目的通过研究Linux的线程机制和信号量实现读者写者问题(Reader-Writer Problem )的并发控制。
第10课进程间的制约关系(经典同步问题)

顾客程序 customer() { V(custs); //释放顾客 P(barbs); //申请理发师 get_haircut(); }
“理发店”问题---P、V信号量解法
设置同步信号量
custs:记录等待理发的顾客数(不包括正在理
发的顾客),初值为0; barbs:正在等待为顾客理发的理发师数,初值 为k;
为防止死锁发生可采取的措施:
最多允许4个哲学家同时坐在桌子周围 仅当一个哲学家左右两边的筷子都可用时, 才允许他拿筷子 给所有哲学家编号,奇数号的哲学家必须首 先拿左边的筷子,偶数号的哲学家则反之
哲学家就餐问题—解法2
0
设置5个互斥信号量: chopstick[i] (0≤i≤4) //对应筷子 初值=1 设置信号量seat // 代表了座位数 初始值=4;
设置变量waiting,它的初值为0。
记录等待理发的顾客数
“理发店”问题---P、V信号量解法
理发师程序 barber() { P(custs); cut_hair(); V(barbs); }
顾客程序 customer() { if(waiting<n) { waiting=waiting+1; V(custs); P(barbs); get_haircut(); } }
第i个哲学家的“思考-就餐-思考”过程可描述为:
philosopher(i) { while(TRUE) { think(); P(chopstick[i]); P(chopstick[(i+1) mod 5)]; eat(); V(chopstick[i]); V(chopstick[(i+1) mod 5)]; } }
OS课程设计__读者写者

兰州交通大学操作系统课程设计课程:计算机操作系统题目:进程同步(读者--写者)班级:姓名:学号:指导教师:日期:2012年12月21日目录1题目 (1)2设计概述 (1)2.1问题描述 (1)2.2采用信号量机制 (1)3课程设计目的及功能 (1)3.1设计目的 (1)3.2设计功能 (1)4总体设计思想概述 (2)4.1功能流程图 (2)4.2开发平台及源程序的主要部分 (3)4.3数据结构 (3)4.4模块说明 (3)4.5源程序 (3)5测试用例,运行结果与运行情况分析 (12)5.1测试用例 (12)5.2运行结果 (12)5.3运行结果分析 (14)6总结与心得 (15)1题目进程同步模拟设计——读者和写者问题2设计概述2.1问题描述模拟用信号量机制实现读者和写者问题,即有两组并发进程:读者和写者,共享一组数据区,进行读写操作,要求任一时刻“写者”最多只允许一个,而“读者”则允许多个。
2.1.1要求允许多个读者同时执行读操作;不允许读者、写者同时操作;不允许多个写者同时操作。
2.1.2读者和写者的相互关系:2.2采用信号量机制1)Wmutex表示读写的互斥信号量,初值: Wmutex =1;2)公共变量Rcount表示“正在读”的进程数,初值:Rcount =0;3)Rmutex:表示对Rcount的互斥操作,初值:Rmutex=1。
3课程设计目的及功能3.1设计目的通过实验模拟读者和写者之间的关系,了解并掌握他们之间的关系及其原理。
由此增加对进程同步的问题的了解。
具体如下:1)掌握基本的同步互斥算法,理解读者和写者模型;2)了解windows中多线程(多进程)的并发执行机制,线程(进程)间的同步和互斥;3)学习使用windows中基本的同步对象,掌握相应的API。
3.2设计功能利用模拟用信号量机制实现读者和写者问题:通过用户控制读进程和写进程,反应读者和写者问题中所涉及的进程的同步与互斥。
进程同步模拟设计——读者和写者问题

学号:课程设计题目进程同步模拟设计——读者和写者问题学院计算机科学与技术学院专业、班级、姓名、指导教师吴利军2013 年01 月17 日课程设计任务书学生:指导教师:吴利军工作单位:计算机科学与技术学院题目: 进程同步模拟设计——读者和写者问题初始条件:1.预备容:阅读操作系统的进程管理章节容,对进程的同步和互斥,以及信号量机制度有深入的理解。
2.实践准备:掌握一种计算机高级语言的使用。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.模拟用信号量机制实现读者和写者问题。
2.设计报告容应说明:⑴需求分析;⑵功能设计(数据结构及模块说明);⑶开发平台及源程序的主要部分;⑷测试用例,运行结果与运行情况分析;⑸自我评价与总结:i)你认为你完成的设计哪些地方做得比较好或比较出色;ii)什么地方做得不太好,以后如何改正;iii)从本设计得到的收获(在编写,调试,执行过程中的经验和教训);iv)完成本题是否有其他方法(如果有,简要说明该方法);时间安排:设计安排一周:周1、周2:完成程序分析及设计。
周2、周3:完成程序调试及测试。
周4、周5:验收、撰写课程设计报告。
(注意事项:严禁抄袭,一旦发现,一律按0分记)指导教师签名:年月日系主任(或责任教师)签名:年月日1 需求分析所谓读者写者问题,是指保证一个 writer 进程必须与其他进程互斥地访问共享资源的同步问题.读者写者问题可以这样的描述,有一群写者和一群读者, 写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是只能有一个写者在写书,并且读者优先,也就是说,读者和写者同时提出请求时,读者优先.当读者提出请求时需要有一个互斥操作, 另外需要有一个信号量 mutex来当前是否可操作.信号量机制是支持多道程序的并发操作系统设计中解决资源共享时进程间的同步与互斥的重要机制,而读者写者问题则是这一机制的一个经典例. 与记录型信号量解决读者—写者问题不同,信号量机制它增加了一个限制,即最多允许n个读者同时读.为此引入了一个信号量Rcount,并赋予初值为 0,通过执行Rcount++操作,来控制读者的数目,每当有一个读者进入时,就要执行Rcount++操作,使 Rcount 的值加1.读者离开时Rcount--;当且仅当Rcount==0时,V (Wmutex),才能进行写操作。
“读写平等”策略的“读者--写者”问题实验报告

淮北师范大学程序设计课程设计采用“读写平等”策略的“读者--写者”问题学院计算机科学与技术专业计算机科学与技术(师范)学号 ***********学生姓名 ***指导教师姓名 ***2012年6月16 日一、设计目的与内容课程设计的目的:操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决问题的机会。
●进一步巩固和复习操作系统的基础知识。
●培养学生结构化程序、模块化程序设计的方法和能力。
●提高学生调试程序的技巧和软件设计的能力。
●提高学生分析问题、解决问题以及综合利用C语言进行程序设计的能力。
设计内容:用高级语言编写和调试一个采用“读写平等”策略的“读者—写者”问题的模拟程序。
设计的要求:1.读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入。
2.读者与写者均有两个以上,可在程序运行期间进行动态增加读者与写者。
3.可读取样例数据(要求存放在外部文件中),进行读者/写者、进入内存时间、读写时间的初始化。
4.要求将运行过程用可视化界面动态显示,可随时暂停,查看阅览室中读者/写者数目、读者等待队列、读写时间、等待时间。
5.读写策略:读写互斥、写写互斥、读写平等(严格按照读者与写者到达的顺序进入阅览室,有写着到达,则阻塞后续到达的读者;有读者到达,则阻塞后续到达的写者)。
有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间,甚至可以是一组处理器寄存器。
有一些只读取这个数据区的进程(reader)和一些只往数据区中写数据的进程(writer)。
以下假设共享数据区是文件。
这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。
这些条件具体来说就是:(1)任意多的读进程可以同时读这个文件;(2)一次只允许一个写进程往文件中写;(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;(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)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
“读者-写者”算法的讨论和改进

“读者-写者”算法的讨论和改进作者:宋锦华李伟来源:《中小企业管理与科技·上旬刊》2011年第05期摘要:读者与写者问题是操作系统中的经典进程同步问题之一,文章利用操作系统中的信号量及信号量上的P、V操作,按照教学的方法和思路对传统的读者-写者算法进行了探讨,并将算法加以改进,实现了写者优先功能,同时保证多个并发进程在执行过程中的正确性。
关键词:读者与写者操作系统信号量1 相关概念1.1 利用信号量解决进程间的制约关系多道程序设计环境下,系统中同时执行多个作业进程,这些进程同时共享和竞争系统中的资源,因此必然存在一定的制约关系。
进程间的这些制约关系可分为互斥与同步两种。
互斥即:一个进程对系统中的共享变量或临界资源进行操作时,为了保证它和系统中其它进程的正确执行,不允许其它进程同时对这些共享变量和临界资源进行操作。
同步指:一个进程运行到了某一点时,需要等待其它进程完成某种操作或发来信息,才能继续运行。
那么,如何来控制进程间的互斥和同步,使它们正确运行呢?利用信号量以及信号量上的P、V操作能够很好的解决进程间的互斥与同步关系,从而保证进程的正确执行。
对于互斥来说,假定设置信号量为S,那么,将S的初值设为1,在临界区之前安排P(S)操作,临界区之后安排V(S)操作即可。
对于同步来说,信号量S的初值设为0,在请求同步点安排P(S)操作,在准备同步条件点安排V(S)操作即可。
本文讨论的是操作系统中很经典的进程同步问题之一——读者写者问题。
1.2 传统的读者写者问题一批数据被多个并发进程共享使用。
其中一些进程只要求读数据,因此称为“读者”,一些进程会对数据进行修改,称为“写者”。
多个读者共同工作时,访问不会有问题,但是读者和写者共同访问或者写者和写者共同修改数据时,就有可能会出错,导致错误的访问结果。
因此,关于读者和写者的读写限制,可以分为这样三条:①写-写互斥,即不能有两个写者同时对数据进行写操作。
读者写者问题实验报告

读者写者问题实验报告引言读者写者问题是计算机科学中经典的同步问题之一,它涉及多线程编程中的资源竞争与同步机制。
通过对读者写者问题的研究,我们可以深入理解线程同步的重要性,并掌握解决并发编程中可能出现的竞争条件和死锁等问题的方法。
在本实验中,我们将设计并实现一个简单的读者写者问题的解决方案,并通过模拟多个读者和写者的并发访问来验证方案的正确性和效果。
问题描述读者写者问题可描述为:有一共享资源(如文件、数据库等),读者可同时访问共享资源进行读取操作,但写者在进行写入操作时,不可同时被其他任何读者或写者访问。
读者和写者的并发访问需要由线程同步机制来保证共享资源的一致性和完整性。
实验设计与实现为了解决读者写者问题,我们需要考虑以下几个关键点:1. 共享资源的访问控制我们可以使用互斥量(Mutex)来实现对共享资源的访问控制。
当一个线程访问共享资源时,它需要先获得互斥量的锁,如果锁已被其他线程占用,则线程进入等待状态,直到锁可用。
一旦线程完成对共享资源的访问,它将释放锁,以便其他线程继续访问。
2. 读者与写者的优先级在读者写者问题中,我们往往需要设定某个优先级规则,以确定读者和写者之间的调度顺序。
一种常见的策略是给予写者优先级,即当一个写者在等待访问共享资源时,其他读者都必须等待。
这样做是为了避免写者长时间等待,以免造成饥饿问题。
3. 记录读者和写者的数量为了控制读者和写者的并发访问,我们需要记录当前同时访问共享资源的读者和写者的数量。
我们可以使用整数变量来记录读者和写者的数量,并通过信号量来保证对这些计数变量的互斥访问。
4. 同步机制的设计在实现读者写者问题的解决方案时,我们需要考虑如何合理地使用互斥量和信号量,并结合优先级规则来实现读者和写者的同步。
这需要通过仔细的设计和调试来确保解决方案的正确性。
实验结果与分析我们基于上述设计实现了一个读者写者问题的解决方案,并进行了多次仿真实验。
实验环境•操作系统:Windows 10•编程语言:C++•编译器:GCC实验步骤1.编写读者和写者线程的代码,其中涉及到对共享资源的读取和写入操作,以及对计数变量和互斥量的访问操作。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统OS报告读者与写者问题(进程同步问题) 沈阳理工大学课程设计专用纸 No1目录一、课程设计目的及要求 ................................ 1 二、相关知识 .......................................... 1 三、题目分析 .......................................... 2 四、概要设计 .......................................... 4 五、代码及流程 ........................................ 5 六、运行结果 ......................................... 11 七、设计心得 ......................................... 12 八、参考文献 (12)1沈阳理工大学课程设计专用纸 No1一、课程设计目的及要求读者与写者问题(进程同步问题)用n 个线程来表示n个读者或写者。
每个线程按相应测试数据文件的要求,进行读写操作。
请用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制:1)写-写互斥;2)读-写互斥;3)读-读允许;写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
二、相关知识Windows API:在本实验中涉及的API 有:1线程控制:CreateThread 完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。
HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SDDWORD dwStackSize, // initial stack sizeLPTHREAD_START_ROUTINE lpStartAddress, // threadfunctionLPVOID lpParameter, // thread argumentDWORD dwCreationFlags, // creation optionLPDWORD lpThreadId // thread identifier);2 ExitThread 用于结束当前线程。
VOID ExitThread(DWORD dwExitCode // exit code for this thread);3 Sleep 可在指定的时间内挂起当前线程。
VOID Sleep(DWORD dwMilliseconds // sleep time);4信号量控制:WaitForSingleObject 可在指定的时间内等待指定对象为可用状态;DWORD WaitForSingleObject(HANDLE hHandle, // handle to objectDWORD dwMilliseconds // time-out interval);1沈阳理工大学课程设计专用纸 No1hHandle为等待的对象,也就是实现同步或者互斥的对象。
该函数一执行,相应的信号量就减去1,如果信号量小于等于0,那么他一直在循环。
5 实现信号量互斥和同步CreateSemaphore用于创建信号量,根据参数的不同可以利用它实现互斥和同步。
ReleaseSemaphore用于释放信号量,使用后相应的信号量加1HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,//SDLONG,lInitialCount, //initial countLONG,lMaximumCount, //maximum countLPCTSTR lpName //object name);ReleaseSemaphore(HANDLE hSemaphore, //handle to semaphoreLONG lRelseaseCount, //cont increment amountLPLONG lpPreviousCount //previous count);三、题目分析将所有的读者和所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。
(1)构筑读者进程和写者进程间的临界区题目中说的一批数据被多个读者、写者共享使用,允许多个读者同时访问这些数据,但是如果有一个写者在访问数据时,就不允许其他读者或写者使用,所以,对这一批数据既要保证读者和写者互斥使用,也要保证写者与写者互斥使用。
也就是说,在读者进程程序中,使用数据的程序段应该构成临界区;在写者进程程序中,使用数据的程序段应该构成临界区。
(2)判定是否是第一个读者根据上面的分析,希望在读者进程中有一个办法能判定请求进入临界区的是否是第一个读者。
如果是第一个读者,就对信号量wsem做P操作,以取得和写者的同步。
为此,设置一个变量rfirst,初值为0.任何一个读者运行时,都现在rfirst上加1,然后判定他是否取值为1.如果是1,则做P(wrt),否则不做。
(3)判定是否是第一个写者原理同(2)判定是否为第一个读者。
(4)写者优先问题的解决需要用到的如下的信号量和变量rsem: 初值为1的互斥信号量,在至少有一个写者准备访问数据时就不允许随后来的读者访问数据wserm: 初值为1的互斥信号量,之后有一个写者访问数据时其他写者和读者就被阻止对数据的访问ReadMutex: 创建写者的互斥信号量,初值为1WriteMutex: 创建读者的互斥信号量,初值为1z: 初值为1的互斥信号量,在至少有一个写着准备访问数据、且后面已经来一个读者时再来的读者将在这个信号量上等待2沈阳理工大学课程设计专用纸 No1 rifrrst:读者计数变量,初值为0wfirst:写者计数变量,初值为0写者优先的PV原语:reader(i): Writer():{ {P(z); P(WriteMutex);P(rsem); wfirst=wfirst+1;P(ReadMutex); if(wfirst==1)rfirst=rfirst+1; P(rsem);if(rfirst==1) V(WritedMutex);P(wsem); P(wsem);V(ReadMutex); 改写所需数据;V(rsem); V(wsem);V(z); P(WriteMutex);读取所需数据; wfirst=wfirst-1;P(ReadMutex); if(wfirst==0)rfirst=rfirst-1; V(rsem);if(rfirst==0) V(WriteMutex);V(wsem); }V(ReadMutex);}读者写者图3.1读者-写者的完整流程框图3沈阳理工大学课程设计专用纸 No1 (5)读者优先与写者优先算法相反,有一个读者优先的算法,即只要有读者在读数据,写者被拒绝在临界区外面,如果有源源不断的写者来,但是只要写者不是第一个,那么写者将会永远被拒绝在临界区外面。
wrt::初值为1的互斥信号量,只要有一个写者访问数据,则其他写者和读者就要被阻止对数据的访问。
mutex:保证读者互斥操作first的信号量,初值为1first :读者计数变量,初值为0读者优先的PV原语:read():{P(mutex);first = first+1; write(): if(first == 1) { P(wrt);P(wrt); V(mutex);对数据进行修改; 读取所需数据V(wrt); P(mutex); } first = first+1;if(first == 0)V(wrt);V(mutex);}四、概要设计(1)控制流程用CheckPersonList(PersonLists)函数检查PersonLists中是否有为创建的进程(读写者)。
如果有则创建相应的读写线程(2)创建读写者用bool CreateReader(int StartTime,int WorkTime)函数创建读者写者相应的线程,其中由windows提供的函数为CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);返回的是DWORD型变量。
在CreateReader(int StartTime,int WorkTime)中还会初始化相应的读写者的基本信息,例如何时申请数据何时读数据何时关闭线程等等。
(3)读写者进程参见图2.1读者-写者的完整流程图。
(4)同步与互斥WaitForSingleObject(信号量名字,infinite)和ReleaseSemaphore(信号量名字,1,null)用于实现同步于互斥,执行WaitForSingleObject(信号量名字,infinite)信号量相应的信号量减1,执行ReleaseSemaphore(信号量名字,1,null)恢复1。
4沈阳理工大学课程设计专用纸 No1五、代码及流程//写者优先算法#include <windows.h> #include <ctype.h>#include <stdio.h>#include <string.h>#include <stdlib.h> #include <malloc.h>#define MAX_PERSON 10 #define READER 01 #define WRITER #define END -1 #define R READER #define W WRITERtypedef struct _Person {HANDLE Thread;int Type;int StartTime;int WorkTime;int ID;}Person;Person Persons[MAX_PERSON]; int NumPerson = 0; long CurrentTime= 0;int PersonLists[] = {1,R,1,3,2,W,2,5,/*读写互斥*/3,W,5,5,/*写写互斥*/4,R,3,5,/*写读互斥*/5,R,15,2,/*读读不互斥*/END,};int rfirst = 0;int wfirst = 0;int NumOfReaders = 0; int NumOfWriters = 0;5沈阳理工大学课程设计专用纸 No1 HANDLE rsem;/*初值为1的互斥信号量,在至少有一个写者准备访问数据时就不允许随后来的读者访问数据*/HANDLE wsem;/*初值为1的互斥信号量,之后有一个写者访问数据时其他写者和读者就被阻止对数据的访问*/HANDLE z;/*初值为1的互斥信号量,在至少有一个写着准备访问数据、且后面已经来一个读者时再来的读者将在这个信号量上等待*/HANDLE ReadMutex;/*创建写者的互斥信号量,初值为1*/HANDLE WriteMutex;/*创建读者的互斥信号量, 初值为1*/void CheckPersonList(int *pPersonList);/*查看人数,为创建读写者线程*/ bool CreateReader(int StartTime,int WorkTime);bool CreateWriter(int StartTime,int WorkTime);DWORD WINAPI ReaderProc(LPVOID lpParam);/*读者进程程序*/ DWORD WINAPI WriterProc(LPVOID lpParam);/*写着进程程序*/#include "Writerprior.h"int main(){rsem = CreateSemaphore(NULL,1,1,NULL);wsem = CreateSemaphore(NULL,1,1,NULL);z = CreateSemaphore(NULL,1,1,NULL);ReadMutex = CreateSemaphore(NULL,1,1,NULL);WriteMutex = CreateSemaphore(NULL,1,1,NULL);CurrentTime = 0;while(true)//模拟20个时钟周期{CheckPersonList(PersonLists);CurrentTime++;Sleep(600);printf("当前时间 = %d:\n",CurrentTime); if(CurrentTime==20)break;}system("pause");CloseHandle(rsem);CloseHandle(wsem);CloseHandle(z);CloseHandle(ReadMutex);CloseHandle(WriteMutex);return 0;6沈阳理工大学课程设计专用纸 No1 }void CheckPersonList(int *pPersonLists) { int i=0;int *pList = pPersonLists;bool P;while(pList[0] != END){if(pList[2] == CurrentTime){switch(pList[1]){case R:P = CreateReader(pList[2],pList[3]);//创建一个读者break;case W:P = CreateWriter(pList[2],pList[3]);//创建一个写者break;}if(!P)printf("Create Person %d is wrong\n",pList[0]);}pList += 4; // 数组的指针指向第二个人}}DWORD WINAPI ReaderProc(LPVOID lpParam) {Person *pPerson = (Person*)lpParam;pPerson->ID = ++NumOfReaders;WaitForSingleObject(z,INFINITE);//P(z),其余读者在此排队printf("\t\t读者 %d 申请读数据...\n",pPerson->ID);WaitForSingleObject(rsem,INFINITE);//P(rsem),一个读者与一个写着再次竞争数据的使用权//printf("Reader %d is requesting the Shared Buffer...\n",pPerson->ID);WaitForSingleObject(ReadMutex,INFINITE);//P(ReadMutex),读者请求进入rfirst临界区rfirst++;if(rfirst == 1)//是否是第一个读者7沈阳理工大学课程设计专用纸 No1{WaitForSingleObject(wsem,INFINITE);//读者在此处与写者进行同步}ReleaseSemaphore(ReadMutex,1,NULL);//退出rfirst临界区,V(ReadMutex) ReleaseSemaphore(rsem,1,NULL);ReleaseSemaphore(z,1,NULL);//V(z)// 读取所需数据,将现在时间赋值给读者,用以计算结束时间printf("\t\t读者 %d 申请成功\n",pPerson->ID);pPerson->StartTime = CurrentTime;printf("\t\t读者 %d 正在读数据...\n",pPerson->ID);while(CurrentTime < pPerson->StartTime + pPerson->WorkTime){// 模拟读数据}printf("\t\t读者 %d 读完数据退出\n",pPerson->ID); WaitForSingleObject(ReadMutex,INFINITE);rfirst--;if(rfirst == 0) //是最后一个读者,ReleaseSemaphore(wsem,1,NULL);//没有读者了,写者放行ReleaseSemaphore(ReadMutex,1,NULL);//退出读者临界区ExitThread(0);//关闭读者线程return 0;}DWORD WINAPI WriterProc(LPVOID lpParam)//写者进程程序{Person *pPerson = (Person*)lpParam;pPerson->ID = ++NumOfWriters;printf("\t\t写者 %d 正在申请写数据...\n",pPerson->ID); WaitForSingleObject(WriteMutex,INFINITE);//请求进入写者临界区wfirst=wfirst++;if(wfirst==1){WaitForSingleObject(rsem,INFINITE);//一个写者在此与读者取得同步}ReleaseSemaphore(WriteMutex,1,NULL);//退出rfirst临界区8沈阳理工大学课程设计专用纸 No1WaitForSingleObject(wsem,INFINITE);//其他写者在此等候进入写临界区// 读取所需数据,将现在时间赋值给读者,用以计算结束时间pPerson->StartTime = CurrentTime;printf("\t\t写者 %d 正在写数据...\n",pPerson->ID);while(CurrentTime < pPerson->StartTime + pPerson->WorkTime) {//模拟写数据}printf("\t\t写者 %d 写完数据退出\n",pPerson->ID);ReleaseSemaphore(wsem,1,NULL);//退出进入写临界区WaitForSingleObject(WriteMutex,INFINITE);//请求进入wfirst临界区wfirst=wfirst--;if(wfirst==0)//是最后一个写者,{ReleaseSemaphore(rsem,1,NULL);//没有写者了,向读者放行}ReleaseSemaphore(WriteMutex,1,NULL);//退出wfirst临界区ExitThread(0);//关闭写者线程return 0;}bool CreateReader(int StartTime,int WorkTime) {DWORD dwThreadID;Person *pPerson = &Persons[NumPerson];pPerson->StartTime = StartTime;pPerson->WorkTime = WorkTime;pPerson->Type = READER;NumPerson++;// 创建一个读者的新线程pPerson->Thread =CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);if(pPerson->Thread == NULL)return false;return true;}bool CreateWriter(int StartTime,int WorkTime)9沈阳理工大学课程设计专用纸 No1 {DWORD dwThreadID;if(NumPerson >= MAX_PERSON)return false;Person *pPerson = &Persons[NumPerson];pPerson->StartTime = StartTime;pPerson->WorkTime = WorkTime;pPerson->Type = WRITER;NumPerson++;// 创建一个写者的新线程pPerson->Thread =CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID);if(pPerson->Thread == NULL)return false;return true;}10沈阳理工大学课程设计专用纸 No1 六、运行结果图6.1 运行结果结果分析:顺序开始时间(s) 执行时间(s) 1 1 3Reader 2 3 53 15 2Writer 1 2 52 5 5表6.1如上表,第一个读者1到达时间是第1s,执行时间是3s,即在第4s的时候结束,而在第2s的时候就写者1到达。