读者—写者问题程序设计
操作系统课程设计报告——读者写者问题
操作系统课程设计课题:读者写者问题姓名:赫前进班级: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 个读者或写者。
每个线程按相应测试数据文件(格式见下)的要求进行读写操作。
实验五 读者-写者问题
实验题目:实验五读者-写者问题完成人:报告日期:一、实验内容简要描述1)创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
2)读者-写者问题的读写操作限制(包括读者优先和写者优先):写-写互斥,即不能有两个写者同时进行写操作。
读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
●读-读允许,即可以有一个或多个读者在读。
3)读者优先的附加限制:如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
4)写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
5)运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、程序设计1、设计思路将所有读者和所有写者分别存于一个读者等待队列和一个写者等待队列中,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作。
2、主要数据结构1)读者优先读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=0时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_count变量。
因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读-写互斥,当read_count=l时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权。
进程同步模拟设计——读者和写者问题
附件1:学号:012081034课程设计进程同步模拟设计——读者和题目写者问题学院计算机科学与技术学院专业计算机科学与技术班级计算机科学与技术姓名指导教师2011 年 1 月19 日目录目录 (1)1 设计概述 (4)1.1问题描述: (4)1.1.1规则: (4)1.1.2读者和写者的相互关系: (4)1.2采用信号量机制 (4)1.3 C++语言程序模拟用信号量机制实现生产者和消费者问题 (5)2课程设计目的及功能 (5)2.1 设计目的 (5)2.2 设计功能: (5)3 需求分析,数据结构或模块说明(功能与框图) (5)3.1数据结构 (5)3.2模块说明 (6)3.3开发平台及源程序的主要部分 (6)3.3.1写操作的设计: (6)3.3.2读操作的设计: (7)3.3.3主函数的设计: (9)3.4 功能流程图 (12)4测试用例,运行结果与运行情况分析 (12)4.1测试用例 (12)4.2运行结果 (13)4.3运行情况分析 (14)5自我评价与总结 (15)6 参考文献 (16)课程设计任务书学生姓名:专业班级:计算机科学与技术指导教师:工作单位:计算机科学与技术学院题目: 进程同步模拟设计——读者和写者问题初始条件:1.预备内容:阅读操作系统的进程管理章节内容,对进程的同步和互斥,以及信号量机制度有深入的理解。
2.实践准备:掌握一种计算机高级语言的使用。
要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.模拟用信号量机制实现读者和写者问题。
2.设计报告内容应说明:⑴课程设计目的与功能;⑵需求分析,数据结构或模块说明(功能与框图);⑶源程序的主要部分;⑷测试用例,运行结果与运行情况分析;⑸自我评价与总结:i)你认为你完成的设计哪些地方做得比较好或比较出色;ii)什么地方做得不太好,以后如何改正;iii)从本设计得到的收获(在编写,调试,执行过程中的经验和教训);iv)完成本题是否有其他的其他方法(如果有,简要说明该方法);v)对实验题的评价和改进意见,请你推荐设计题目。
读者-写者问题解答计算机操作系统实验报告指导资料
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)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
操作系统课程设计 (4)
设计1 题目进程同步(读者-写者问题)一、问题描述与分析一个数据文件或记录,可被多个进程共享,我们把只要求读该文件的进程称为“Reader”进程,其他进程则称为“Writer进程”允许多个进程同时读一个共享对象,因为读操作不会使数据文件混乱。
但不允许一个Writer进程和其他Reader进程或Writer进程同时访问将会引起混乱。
所谓读者写者问题,是指保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书,并且,读者必写者优先,也就是说,读者和写者同时提出请求时,读者优先。
当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S 来当前是否可操作。
二、设计要求和目的1.设计要求通过解决读者写者问题实现进程同步。
即(1)实现写-写互斥,(2)读-写互斥(3)读-读允许(4)写者优先2. 设计目的(l).用信号量来实现读者写者问题,掌握进程同步机制及其实现机理。
(2).理解和运用信号量、PV原语、进程间的同步互斥关系等基本知识。
三、背景知识1.参考操作系统课本中关于进程同步这方面的知识以及结合老师上课的讲解,仔细研究利用信号量实现读写者问题。
读者写者问题的定义如下:有一个许多进程共享的数据区,这个数据区可以是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)和一些只往数据区写数据的进程(Writer),此外还需要满足以下条件:(1)任意多个读进程可以同时读这个文件;(2)一次只有一个写进程可以往文件中写;(3)如果一个写进程正在进行操作,禁止任何读进程度文件。
我们需要分两种情况实现该问题:读优先:要求指一个读者试图进行读操作时,如果这时正有其他读者在进行操作,他可直接开始读操作,而不需要等待。
写优先:一个读者试图进行读操作时,如果有其他写者在等待进行写操作或正在进行写操作,他要等待该写者完成写操作后才开始读操作。
“读写平等”策略的“读者--写者”问题实验报告
淮北师范大学程序设计课程设计采用“读写平等”策略的“读者--写者”问题学院计算机科学与技术专业计算机科学与技术(师范)学号 ***********学生姓名 ***指导教师姓名 ***2012年6月16 日一、设计目的与内容课程设计的目的:操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决问题的机会。
●进一步巩固和复习操作系统的基础知识。
●培养学生结构化程序、模块化程序设计的方法和能力。
●提高学生调试程序的技巧和软件设计的能力。
●提高学生分析问题、解决问题以及综合利用C语言进行程序设计的能力。
设计内容:用高级语言编写和调试一个采用“读写平等”策略的“读者—写者”问题的模拟程序。
设计的要求:1.读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入。
2.读者与写者均有两个以上,可在程序运行期间进行动态增加读者与写者。
3.可读取样例数据(要求存放在外部文件中),进行读者/写者、进入内存时间、读写时间的初始化。
4.要求将运行过程用可视化界面动态显示,可随时暂停,查看阅览室中读者/写者数目、读者等待队列、读写时间、等待时间。
5.读写策略:读写互斥、写写互斥、读写平等(严格按照读者与写者到达的顺序进入阅览室,有写着到达,则阻塞后续到达的读者;有读者到达,则阻塞后续到达的写者)。
有一个被许多进程共享的数据区,这个数据区可以是一个文件,或者主存的一块空间,甚至可以是一组处理器寄存器。
有一些只读取这个数据区的进程(reader)和一些只往数据区中写数据的进程(writer)。
以下假设共享数据区是文件。
这些读者和写者对数据区的操作必须满足以下条件:读—读允许;读—写互斥;写—写互斥。
这些条件具体来说就是:(1)任意多的读进程可以同时读这个文件;(2)一次只允许一个写进程往文件中写;(3)如果一个写进程正在往文件中写,禁止任何读进程或写进程访问文件;(4)写进程执行写操作前,应让已有的写者或读者全部退出。
读者于写者问题课程设计
读者于写者问题课程设计一、教学目标本课程的教学目标是帮助学生理解并掌握“读者于写者问题”的相关概念和理论,培养学生对于文本的深入解读和批判性思维能力。
具体分为以下三个部分:知识目标:学生能够准确地掌握读者反应理论和作者意图理论的基本概念,了解不同读者和写者对于文本的影响和作用。
技能目标:学生能够运用所学的理论知识,对于给定的文本进行深入解读和分析,并能够就文本内容进行批判性的思考和讨论。
情感态度价值观目标:通过对于不同读者和写者问题的探讨,培养学生尊重多元观点和包容差异的态度,增强对于文本的理解和欣赏能力。
二、教学内容本课程的教学内容主要包括读者反应理论和作者意图理论两个部分。
具体内容包括:1.读者反应理论:介绍读者反应理论的基本概念和主要观点,分析读者的阅读过程和文本理解的影响因素。
2.作者意图理论:讲解作者意图理论的基本原理和应用方法,探讨作者的意图和文本的意义之间的关系。
3.读者与写者的互动:讨论读者和写者之间的相互作用和平衡,分析读者对于文本的影响和写者的创作意图的实现。
三、教学方法为了达到本课程的教学目标,将采用多种教学方法进行教学,包括:1.讲授法:通过教师的讲解和阐述,系统地传授读者反应理论和作者意图理论的相关知识。
2.讨论法:学生进行小组讨论和全班讨论,鼓励学生提出自己的观点和思考,培养学生的批判性思维能力。
3.案例分析法:通过分析具体的案例和文本,让学生亲身体验和理解读者反应理论和作者意图理论的应用和意义。
四、教学资源为了支持和丰富本课程的教学内容和方法,将利用多种教学资源,包括: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)读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。
读者写着问题课程设计
读者写着问题课程设计一、课程目标知识目标:1. 学生能理解并掌握“读者写着问题”的概念,明确其在语文写作中的应用。
2. 学生能分析并评价一篇作文中的“读者写着问题”,提出改进意见。
3. 学生能了解不同文体的写作特点,结合“读者写着问题”进行创作。
技能目标:1. 学生能够运用“读者写着问题”的方法,提高自己的写作能力,使文章更具吸引力。
2. 学生能够通过小组讨论,与他人合作完成一篇作文,提高团队协作能力。
3. 学生能够运用所学知识,对一篇作文进行修改和润色,提升文章质量。
情感态度价值观目标:1. 学生对写作产生兴趣,树立自信心,勇于表达自己的观点。
2. 学生认识到“读者写着问题”在写作中的重要性,培养良好的写作习惯。
3. 学生在写作过程中,学会换位思考,关注读者需求,提高人际沟通能力。
本课程针对初中年级学生,结合语文写作教学实际,以“读者写着问题”为主题,旨在提高学生的写作水平,培养其良好的写作习惯和团队协作能力。
课程目标具体、可衡量,便于教师进行教学设计和评估。
通过本课程的学习,学生将能够更好地应对各类写作任务,提高自己的语文素养。
二、教学内容1. 理论知识:- “读者写着问题”的定义与作用- 不同文体中的“读者写着问题”特点- 如何在写作中关注读者需求,提高文章吸引力2. 实践训练:- 分析优秀作文中的“读者写着问题”应用- 学生现场写作,运用“读者写着问题”方法- 小组合作修改作文,提升文章质量3. 教学案例:- 以教材中相关章节的课文为例,分析“读者写着问题”的应用- 选取学生习作,进行课堂讲评,指出优缺点,并提出改进建议4. 教学进度安排:- 第一课时:导入“读者写着问题”概念,分析教材相关章节内容- 第二课时:优秀作文案例分析,学生现场写作实践- 第三课时:小组合作修改作文,总结“读者写着问题”在写作中的应用教学内容根据课程目标进行选择和组织,确保科学性和系统性。
以教材为依据,结合实际教学需求,制定详细的教学大纲,明确教学内容的安排和进度。
操作系统读者与写者问题课程设计报告
课程设计任务书目录一、课程设计目的及要求 (1)二、相关知识 (1)三、题目分析 (2)四、概要设计 (4)五、代码及流程 (5)六、运行结果 (11)七、设计心得 (12)八、参考文献 (12)一、课程设计目的及要求读者与写者问题(进程同步问题)用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);3Sleep 可在指定的时间内挂起当前线程。
VOID Sleep(DWORD dwMilliseconds // sleep time);4信号量控制:WaitForSingleObject可在指定的时间内等待指定对象为可用状态;DWORD WaitForSingleObject(HANDLE hHandle, // handle to objectDWORD dwMilliseconds // time-out interval);hHandle为等待的对象,也就是实现同步或者互斥的对象。
写者优先的读者—写者问题及解决方案
until false; end
交通计算机
翟高寿
第4页共6页
写者子程序设计
writerj:
begin repeat
wait(mutex); if writercount=0 then wait(S); writercount writercount +1; signal(mutex); wait(wmutex); Perform write operation; signal(wmutex); wait(mutex); writercount writercount -1; if writercount=0 then signal(S); signal(mutex);
parbegin
reader1; … ; readeri ; … ; readerm; writer1; … ; writerj ; … ; writern; parend
end
交通计算机 翟高寿
第3页共6页
读者子程序设计
readeri: begin
repeat
wait(S); wait(rmutex); if readercount=0 then wait(wmutex); readercount readercount +1; signal(rmutex); signal(S); Perform read operation; wait(rmutex); readercount readercount -1; if readercount=0 then signal(wmutex); signal(rmutex);
写者优先的读者-写者问题 及解决方案
交通 计算机
翟高寿
第1页共6页
操作系统之读者与写者问题(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;
读者写者问题 ----写者优先
读者写者问题 ----写者优先#include "windows.h"#include <conio.h>#include <stdlib.h>#include <fstream.h>#include <io.h>#include <string.h>#include <stdio.h>#define INTE_PER_SEC 1000 //每秒时钟中断的数目#define MAX_THREAD_NUM 64 //最大线程数#define MAX_FILE_NUM 32 //最大文件数目数#define MAX_STR_LEN 32 //字符串的长度FILE * file;FILE * inFile;int readcount=0; //读者数目int writecount=0; //写者数目//临界资源CRITICAL_SECTION cs_Write;CRITICAL_SECTION cs_Read;struct ThreadInfo{ int serial; //线程序号char entity; //线程类别(判断是读者还是写者线程) double delay; //线程延迟时间double persist; //线程读写操作时间};//写者优先---读者线程//P:读者线程信息void WP_ReaderThread(void *p){//互斥变量HANDLE h_Mutex1=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex1");HANDLE h_Mutex2=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex2");DWORD wait_for_mutex1; //等待互斥变量所有权DWORD wait_for_mutex2;DWORD m_delay=(DWORD)(((ThreadInfo*)(p))->delay *INTE_PER_SEC); //延迟时间DWORD m_persist=(DWORD)(((ThreadInfo*)(p))->persist *INTE_PER_SEC); //读文件持续时间int m_serial=((ThreadInfo*)(p))->serial ; //线程的序号Sleep(m_delay); //延迟等待printf("Reader thread %d sents the reading require.\n",m_serial);fprintf(file,"Reader thread %d sents the reading require.\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){ // 如果是第1个读者,等待写者写完EnterCriticalSection(&cs_Write);}ReleaseMutex(h_Mutex2);// 释放互斥信号Mutex2//让其他读者进去临界区LeaveCriticalSection(&cs_Read);ReleaseMutex(h_Mutex1);//读文件printf("Reader thread %d begins to read file.\n",m_serial);fprintf(file,"Reader thread %d begins to read file.\n",m_serial);Sleep(m_persist);//退出线程printf("Reader thread %d finished reading file.\n",m_serial); fprintf(file,"Reader thread %d finished reading file.\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 wait_for_mutex3; //互斥变量DWORD m_delay; //延迟时间DWORD m_persist; //读文件持续时间int m_serial; //线程序号HANDLE 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("Writer thread %d sents the reading require.\n",m_serial);fprintf(file,"Writer thread %d sents the reading require.\n",m_serial);wait_for_mutex3=WaitForSingleObject(h_Mutex3,-1);writecount++; //修改写者数目if(writecount==1){EnterCriticalSection(&cs_Read);}ReleaseMutex(h_Mutex3);EnterCriticalSection(&cs_Write);printf("Writer thread %d begins to write to the file.\n",m_serial);fprintf(file,"Writer thread %d begins to write to the file.\n",m_serial);Sleep(m_persist);printf("Writer thread %d finished writing to the file.\n",m_serial);fprintf(file,"Writer thread %d finished writing to the file.\n",m_serial);LeaveCriticalSection(&cs_Write);wait_for_mutex3=WaitForSingleObject(h_Mutex3,-1);writecount--;if(writecount==0){LeaveCriticalSection(&cs_Read);}ReleaseMutex(h_Mutex3);}///////////////////////////////////////////////写者优先处理函数// file:文件名int main(int argc,char *argv[]){DWORD n_thread=0;DWORD thread_ID;DWORD wait_for_all;HANDLE h_Mutex1=CreateMutex(NULL,FALSE,"mutex1");HANDLE h_Mutex2=CreateMutex(NULL,FALSE,"mutex2");HANDLE h_Mutex3=CreateMutex(NULL,FALSE,"mutex3");HANDLE h_Thread[MAX_THREAD_NUM];ThreadInfo thread_info[MAX_THREAD_NUM];InitializeCriticalSection(&cs_Write);InitializeCriticalSection(&cs_Read);int a;char c;int b;int d;file=fopen("thread.txt","r");if(file!=NULL){while(!feof(file)){fscanf(file,"%d %c %d%d\n",&a,&c,&b,&d);thread_info[n_thread].serial=a;thread_info[n_thread].delay=b;thread_info[n_thread].entity=c;thread_info[n_thread++].persist=d;}}fclose(file);if((file=fopen("output.txt","w"))==NULL){cout<<"can not open the output.txt file"<<endl;}fprintf(file,"%s","start\n");for(int i=0;i<(int)(n_thread);i++){if(thread_info[i].entity=='R'||thread_info[i].entity =='r'){ //创建读者进程h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_ReaderThread),& thread_info[i],0,&thread_ID);} else{ //创建写线程h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_WriterThread),&t hread_info[i],0,&thread_ID);}}//等待所有的线程结束wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);printf("All reader and writer have finished operating.\n");fclose(file);return 0;}。
读者写者问题C源代码
读者——写者问题C++程序(原创作品)演示效果图:程序完整代码:#include <>#include <>#include <>#include <>#include<string>#include<>."<<endl; " << endl;();者 2.写者"<<endl;cin>>ru; waitSemapore--;}}}else {wait=next;waitSemapore--;}}}//writer is endnext++;}//1while()if(type==1){cout<<"~"<<"读者"<<readc<<"读完毕,释放资源"<<endl;readc++;empty++;//读者用的,但是为了在输出时演示出运行状态,不得不将其放在此处Sleep(3000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()}elseif(type==2){cout<<"~"<<"写者"<<writc<<"写完毕,释放资源" << endl;writc++;wrIn++;//V操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放在此处empty++;//V操作改变信号量,写者用,但是为了在输出时演示出运行状态,不得不将其放在此处Sleep(3000);/////////////////////////////////////////////////////////////////////////////////////////////sleep()cout<<endl;}}//2while()return 0;}/////////////////////////////////////////////////////主函数结束。
读者写者问题实验报告
读者写者问题实验报告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.本程序主要用于说明阅读者写入者问题中的资源互斥访问的调动策略,并模仿其访问的过程。
采用书上的伪码编制而成,实际上采用的是读优先策略。
2.在本程序中用于表现的图形界面说明:在程序编译运行后会出现中间一个大的圆圈表示公用的资源,上面一排五个矩形表示5个读者,下面的五个矩形表示五个写入者。
每个读者和写入者都有3种状态,休息,等待和操作(读入或者写入)分别用黑颜色,绿颜色,红颜色表示休息,等待和操作。
一旦操作者获得资源,可以进行读或者写,我们就划一条从操作者中心到资源中心的线,表示开始操作。
三、关于阅读者写入者问题的mfc程序分析:A. ReaderAndWriter.c函数说明:B.Mutex.c函数说明:1. DWORD WINAPI ReaderThread (LPVOID pVoid)读者进程:根据前面的资源分配策略,对于读进程,我们初始化设置都是处于休息状态,然后要是资源可读,根据进程到来的快慢,分配资源给读者,是其从休息,等待到读状态,最后释放资源进入休息状态,一直循环。
一旦有一个读者进入临界区,我们就封锁临界区,可以让所用的读者进入,而不让写入者进入,并用一个资源控制readercount,保证每次只有一个进程对变量进行操作。
这样,直到每一个读者都读完,没有一个读者的时候,开始释放临界区,这样写入者就可以进入与读者进行资源的争夺,决定是读还是写。
2. DWORD WINAPI WriterThread (LPVOID pVoid)写入者进程:与读者进程类似,从休息代等待,最后写入,一直循环。
其中只要一个写进程进入临界区,其他的进程就不能进入临界区了,直到写进程释放临界区。
读者写者问题-操作系统课程设计
者写者问题-操作系统课程设计某某大学课程设计报告课程名称:操作系统课程设计设计题目:读者写者问题系别:计算机系专业:计算机科学与技术组别:第四组学生姓名: 某某某学号:起止日期:指导教师:目录1、需求分析 (1)1.1 课程设计题目 (1)1.2课程任务及要求 (1)1.3课程设计思想 (1)1.4软硬件运行环境及开发工具 (2)2、概要设计 (2)2.1程序流程图 (2)2.2所用原理 (3)2.2.1 并发原理 (3)2.2.2 互斥操作原理 (4)2.2.3 面向对象编程编程原理 (4)2.2.4 锁机制原理 (5)2.2.5 线程的原理 (6)2.2.6 读者写者问题的一般应用 (6)3、详细设计 (7)4、调试与操作说明 (16)5、课程设计总结与体会 (18)6、致谢 (19)7、参考文献 (19)1、需求分析1.1课程设计题目课程设计题目:读者写者问题1.2课程任务及要求编写程序实现读者写者算法(读_写互斥,读_读允许,写写互斥)给出解决方案(包括说明设计实现的原理,采用的数据结构等)画出程序的基本结构框图和流程图分析说明每一部分程序的的设计思路实现源代码按期提交完整的程序代码和可执行程序根据要求完成课程设计报告总结1.3课程设计思想读者-写者问题是一个经典的并发程序设计问题。
有两组并发进程:读者和写者,共享文件F,要求:(1)允许多个读者同时对文件执行读操作;(2)只允许一个写者对文件执行写操作;(3)任何写者在完成写操作之前不允许其他读者或写者工作;(4)写者在执行写操作前,应让已有的写者和读者全部退出。
单纯使用信号量不能解决此问题,必须引入计数器readcount对读进程记数。
为了有效的解决读者写者问题,需要引进读者-写者锁,允许多名读者同时以只读的方式存取有锁保护的对象;或一位写者以写方式存取有锁保护的对象。
当一名或多名读者上锁后,此时形成读锁,写者将不能访问有锁保护的对象;当锁被请求者用于写操作时,形成写锁,其他进程的读写操作必须等待。
读者写者
读者写者程序设计1.程序目标功能设计读者-写者问题是保证读进程与写进程互斥地访问共享对象的同步问题,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是读者读的时候写者不能写,写者写的时候读者不能读,但只允许一个写者写这本书。
有一个许多进程共享的数据区,这个数据区可以是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)和一些只往数据区写数据的进程(Writer)。
读者-写者的读写限制(包括读者优先和写者优先)1)写-写互斥,即不能有两个写者同时进行写操作2)读-写互斥,即不能同时有一个读者在读,同时却有一个写者在写3)读读允许,即可以有2个以上的读者同时读2.数据结构设计int readernum=0;int writernum=0;int reader();int writer();int readerexit();int writerexit();3.源程序及注释#include <stdio.h>#include <stdlib.h>#include <windows.h>int readernum=0;int writernum=0;int rmutex=0;int wmutex=0;int reader();int writer();int readerexit();int writerexit();main(){int i;while(1){ printf("《读者写者》\n"); printf("***********\n");printf("1.读者进入 \n");printf("2.写者进入 \n");printf("3.读者退出 \n");printf("4.写者退出 \n");printf("***********\n");scanf("%d",&i);switch(i){case 1:{reader();break;}case 2:{writer();break;}case 3:{readerexit();break;}case 4:{writerexit();break;}default: printf("输入有误,请重新输入\n");}}return 0;}int reader(){if(writernum==1){rmutex++;printf("有写者在写不能读\n");printf("有%d位读者阻塞\n",rmutex);} else{ readernum++;printf("有%d位读者\n",readernum);}}int writer(){if(readernum>0||writernum==1){wmutex++;printf("有读者在读不能写\n");printf("有%d位写者阻塞\n",wmutex);} else{writernum=1;printf("有1位写者\n");}}int readerexit(){if(readernum>0){readernum--;printf("有%d位读者\n",readernum);if(readernum==0){if(wmutex>0||rmutex>0){if(wmutex>0){printf("有%d位写者等待\n",wmutex);} else{ rmutex--;printf("有%d位读者等待\n",rmutex); }}}}else{printf("输入错误,请重新输入\n");}}int writerexit(){if(writernum==1){writernum =0;printf("写者退出\n");if(rmutex>0||wmutex>0){if(wmutex>0){wmutex--;printf("有%d位写者等待\n",wmutex); }else{ rmutex--;printf("有%d位读者等待\n",rmutex); ;}}}else{printf("输入错误\n");}}4.运行结果及分析与总结运行结果出现的界面:按1读者进入出现的界面:按2写者进入的界面:按3读者退出的界面:按4写者退出的界面:实验总结:利用互斥信号量,能够解决资源共享时进程间的同步与互斥的问题,达到了预定的目标。
读者写者问题实验代码
实验内容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(" 读者与写者实验 \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、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
DWORD dwThreadID;
Person *pPerson = &Persons[NumPerson];
pPerson->StartTime= StartTime;
pPerson->WorkTime= WorkTime;
pPerson->Type= READER;
NumPerson++;
//创建一个读者的新线程
实验内容(步骤、表格、算法或流程图等)
概要设计:
(1)控制流程
用CheckPersonList(PersonLists)函数检查PersonLists中是否有为创建的进程(读写者)。如果有则创建相应的读写线程
(2)创建读写者
用bool CreateReader(int StartTime,int WorkTime)函数创建读者写者相应的线程,其中由windows提供的函数为CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);返回的是DWORD型变量。
wsem= CreateSemaphore(NULL,1,1,NULL);
z= CreateSemaphore(NULL,1,1,NULL);
ReadMutex= CreateSemaphore(NULL,1,1,NULL);
WriteMutex= CreateSemaphore(NULL,1,1,NULL);
if(rfirst == 0) //是最后一个读者?
ReleaseSemaphore(wsem,1,NULL);//没有读者了,写者放行
ReleaseSemaphore(ReadMutex,1,NULL);//退出读者临界区
ExitThread(0);//关闭读者线程
return 0;
}
DWORD WINAPI WriterProc(LPVOID lpParam)//写者进程程序
pPerson->Thread = CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);
if(pPerson->Thread == NULL)
return false;
return true;
5,R,15,2,/*读读不互斥*/
END,
};
int rfirst = 0;
int wfirst = 0;
int NumOfReaders = 0;
int NumOfWriters = 0;
HANDLE rsem;/*初值为1的互斥信号量,在至少有一个写者准备访问数据时就不允许随后来的读者访问数据*/
while(CurrentTime < pPerson->StartTime + pPerson->WorkTime)
{
//模拟读数据
}
printf("\t\t读者%d读完数据退出\n",pPerson->ID);
WaitForSingleObject(ReadMutex,INFINITE);
rfirst--;
{
//模拟写数据
}
printf("\t\t写者%d写完数据退出\n",pPerson->ID);
ReleaseSemaphore(wsem,1,NULL);//退出进入写临界区
WaitForSingleObject(WriteMutex,INFINITE);//请求进入wfirst临界区
wPI ReaderProc(LPVOID lpParam);/*读者进程程序*/
DWORD WINAPI WriterProc(LPVOID lpParam);/*写着进程程序*/
#include "Writerprior.h"
int main()
{
rsem= CreateSemaphore(NULL,1,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);
{
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]);//创建一个读者
//读取所需数据,将现在时间赋值给读者,用以计算结束时间
pPerson->StartTime = CurrentTime;
printf("\t\t写者%d正在写数据...\n",pPerson->ID);
while(CurrentTime < pPerson->StartTime + pPerson->WorkTime)
#define READER 0
#define WRITER 1
#define END -1
#define R READER
#define W WRITER
typedef 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,/*写读互斥*/
HANDLE WriteMutex;/*创建读者的互斥信号量,初值为1*/
void CheckPersonList(int *pPersonList);/*查看人数,为创建读写者线程*/
bool CreateReader(int StartTime,int WorkTime);
bool CreateWriter(int StartTime,int WorkTime);
在CreateReader(int StartTime,int WorkTime)中还会初始化相应的读写者的基本信息,例如何时申请数据何时读数据何时关闭线程等等。
(3)读写者进程
参见图2.1读者-写者的完整流程图。
(4)同步与互斥
WaitForSingleObject(信号量名字,infinite)和ReleaseSemaphore(信号量名字,1,null)用于实现同步于互斥,执行WaitForSingleObject(信号量名字,infinite)信号量相应的信号量减1,执行ReleaseSemaphore(信号量名字,1,null)恢复1。
源程序及注释(不足可加附页)
//写者优先算法
#include <windows.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#define MAX_PERSON 10
HANDLE wsem;/*初值为1的互斥信号量,之后有一个写者访问数据时其他写者和读者就被阻止对数据的访问*/
HANDLE z;/*初值为1的互斥信号量,在至少有一个写着准备访问数据、且后面已经来一个读者时再来的读者将在这个信号量上等待*/
HANDLE ReadMutex;/*创建写者的互斥信号量,初值为1*/
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)//是否是第一个读者
{
WaitForSingleObject(wsem,INFINITE);//读者在此处与写者进行同步
}
ReleaseSemaphore(ReadMutex,1,NULL);//退出rfirst临界区,V(ReadMutex)
ReleaseSemaphore(rsem,1,NULL);
用n个线程来表示n个读者或写者。每个线程按相应测试数据文件的要求,进行读写操作。用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制:1)写-写互斥;
2)读-写互斥;
3)读-读允许;
写者优先的附加限制:如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
CurrentTime = 0;