生产者与消费者进程同步问题
- 格式:pdf
- 大小:195.27 KB
- 文档页数:6
学习中心:专业:年级:年春/秋季学号:学生:题目:进程同步与互斥生产者-消费者问题1.谈谈你对本课程学习过程中的心得体会与建议?转眼间,学习了一个学期的计算机操作系统课程即将结束。
在这个学期中,通过老师的悉心教导,让我深切地体会到了计算机操作系统的一些原理和具体操作过程。
在学习操作系统之前,我只是很肤浅地认为操作系统只是单纯地讲一些关于计算机方面的操作应用,并不了解其中的具体操作过程1.1设计思路在这次设计中定义的多个缓冲区不是环形循环的,并且不需要按序访问。
其中生产者可以把产品放到某一个空缓冲区中,消费者只能消费被指定生产者生产的产品。
本设计在测试用例文件中指定了所有生产和消费的需求,并规定当共享缓冲区的数据满足了所有有关它的消费需求后,此共享才可以作为空闲空间允许新的生产者使用。
本设计在为生产者分配缓冲区时各生产者之间必须互斥,此后各个生产者的具体生产活动可以并发。
而消费者之间只有在对同一个产品进行消费时才需要互斥,它们在消费过程结束时需要判断该消费者对象是否已经消费完毕并释放缓冲区的空间。
1.2程序流程图1.3基本内容在设计程序时主要有三个主体部分、三个辅助函数和一个数据结构。
其中主体部分为一个主函数main (),用于初始化缓冲区和各个同步对象,并完成线程信息的读入,最后根据该组的线程记录启动模拟线程,并等待所有线程的运主函数初始化缓冲区,消费请求队列及部分同步对象提取线程信息完成线程相关同步对象的初始化等待所有线程结束创建线程模拟生产和消费程序结束消费者有消费请求?此请求可满足?确定产品位置此产品正被消费?进入临界区(对同一产品进行请求的消费者之间互斥)消费产品、并判断是否应该释放产品所占缓冲区 结束消费进程生产者存在空缓冲区?另一生产者正在生产?进入临界区 (所有生产者之间互斥)从空缓冲区中为本生产者的产品分配一个空间退出临界区在该缓冲区放入产品通过信号量通知等待本产品的消费者结束生产进程退出临界区 YYYNNNNYYN行结束后退出程序;生产者函数Produce()和消费者函数Consume(),生产者和消费者函数运行于线程中完成对缓冲区的读、写动作,根据此处生产消费的模型的特点,生产者和消费者之间通过使用同步对象实现了生产和消费的同步与互斥,是本实验的核心所在。
目录1.需求分析 (2)1.1 课程设计题目 (2)1.2 课程设计任务 (2)1.3 课程设计原理 (2)1.4 课程设计要求 (2)1.5 实验环境 (2)2. 概要设计 (3)2.1 课程设计方案概述 (3)2.2 课程设计流程图 (3)3.详细设计 (4)3.1 主程序模块 (4)3.2 生产者程序模块 (5)3.3 消费者程序模块 (6)4.调试中遇到的问题及解决方案 (6)5.运行结果 (7)6.实验小结 (7)参考文献 (8)附录:源程序清单 (8)1.需求分析1.1 课程设计题目用多线程同步方法解决生产者-消费者问题1.2 课程设计任务(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前指针位置和生产者/消费者线程的标识符。
(2)生产者和消费者各有两个以上。
(3)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。
1.3 课程设计原理生产者和消费者问题是从操作系统中的许多实际同步问题中抽象出来的具有代表性的问题,它反映了操作系统中典型的同步例子,生产者进程(进程由多个线程组成)生产信息,消费者进程使用信息,由于生产者和消费者彼此独立,且运行速度不确定,所以很可能出现生产者已产生了信息而消费者却没有来得及接受信息这种情况。
为此,需要引入由一个或者若干个存储单元组成的临时存储区(即缓冲区),以便存放生产者所产生的信息,解决平滑进程间由于速度不确定所带来的问题。
1.4 课程设计要求(1)有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1~20这20个整型数。
(2)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前指针位置和生产者/消费者线程的标识符。
(3)生产者和消费者各有两个以上。
(4)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。
1.5 实验环境系统平台:LINUX开发语言:C开发工具:PC机一台2. 概要设计2.1 课程设计方案概述本设计中设置一个长度为20的一维数组buff[20]作为有界缓冲区,缓冲区为0时,代表该缓冲区内没有产品,buff[i]=i+1表示有产品,产品为i+1。
一、讨论课名称:计算机操作系统中进程同步与互斥问题分析二、讨论课目的:1.熟悉临界资源、信号量及PV操作的定义与物理意义;2.掌握进程互斥与进程同步的相关知识;3.掌握用信号量机制解决进程之间的同步与互斥问题;4.实现生产者-消费者问题,深刻理解进程同步问题。
三、讨论课内容:1.进程同步的基本概念在多道程序环境下,系统中可能存在许多的进程,在这些进程之间必定存在一些制约关系,这种制约关系表现为以下两种形式:①资源共享关系。
进程之间不知道其他进程的存在,而这些进程又处在同一个系统中,对系统资源必须共享使用,而有些资源不允许进程同时访问,例如打印机。
系统只能保证进程间互斥地使用这种临界资源,称这种资源共享关系叫做互斥;②相互合作关系。
在某些进程间还存在一种相互合作的关系。
例如在某个系统中存在两个进程,输入进程A和计算进程B,A负责向B提供数据,当缓冲区空时,B进程因不能获得所需数据而等待。
当A把数据送入缓冲区后,并向B发送一个信号将B唤醒,B才能取走数据。
同样,当B没有提取数据,也就是说缓冲区满时,进程A也无法向其中投入数据而等待。
这就是一种相互合作关系,称之为进程间的同步关系。
2.信号量机制实现进程同步本文分析的生产者-消费者问题就是一种相互合作问题的代表,对进程同步问题的解决,早在1965年,荷兰科学家Dijkstra就提出信号量机制是一种卓有成效的进程同步工具。
在信号量机制中,信号量仅能通过两个标准的原子操作wait(s)和singnal(s)来访问。
这两个操作被称为P,V操作。
在信号量机制中,除了需要一个用于代表资源数目的整型变量value外,还应增加一个进程链表L,用于链接上述的所有等待进程。
记录型信号量是由于它采用了记录型的数据结构而得名的。
它所包含的上述两个数据项可描述为:type semaphore=recordvalue:integer;L:list of process;End相应地,wait(s)和singal(s)操作可描述为:Procedure wait(s)var s:semaphore;BeginS.value:=S.value-1;If S.value<0 then block(S,L)EndProcedure signal(s)var S:semaphore;BeginS.value:=S.value+1;If S.value<=0 then wakeup(S,L);End每次的wait操作,意味着进程请求一个单位的资源,因此描述为S.value:=S.value-1;当S.value<0时,表示资源已分配完毕,因而进程调用block原语,进行自我阻塞,放弃处理机,并插入到信号量链表S.L中。
进程的同步与互斥之⽣产者消费者问题:对信号量设置的理解及PV操作顺序分析问题描述系统中有⼀组⽣产者进程和⼀组消费者进程,⽣产者进程每次⽣产⼀个产品放⼊缓冲区,消费者进程每次从缓冲区取出⼀个产品并使⽤;缓冲区在同⼀时刻只能允许⼀个进程访问。
问题分析⽣产者、消费者共享⼀个初始为空、⼤⼩为n的缓冲区,我们把缓冲区中未存放数据的⼀个块,当作⼀个“空位”;把其中按块存放的数据当作“产品”。
同步关系:⽣产者与消费者只有缓冲区有空位时,⽣产者才能把产品放⼊缓冲区⽣产者把“空位”当作资源,缓冲区初始为空,即空位数量为n(n:空的缓冲区⼤⼩)所以可以设置信号量empty,初始nempty>0时,有空位,⽣产者可以消耗“空位”这种资源即P(empty);empty<=0时,⽣产者⽆“空位”资源可⽤,便会挂起到阻塞队列等待。
只有缓冲区有产品时,消费者才能从缓冲区中取出产品消费者把“产品”当作资源,缓冲区初始为空,即产品数量为0所以可以设置信号量full,初始为0full<=0,消费者⽆“产品”这种资源可⽤,便会挂起到阻塞队列full>0,有产品,消费者可以消耗“产品”这种资源即P(full)进⼀步:empty>0时,有空位,⽣产者可以消耗“空位”这种资源即P(empty)的同时:⽣产了“产品这种资源”,即V(full);full>0时,有产品,消费者可以消耗“产品”这种资源即P(full)的同时:⽣产了“空位”这种资源,即V(empty);互斥关系:所有进程之间缓冲区是临界资源,各个进程必须互斥地访问设置信号零mutex,初始为1在进⼊区P(mutex)申请资源在退出区V(mutex)释放资源设计typedef struct{int value;Struct process *L; //等待序列}semaphore;semaphore full;semaphore empty;semaphore mutex;//某进程需要使⽤资源时,通过wait原语申请:P操作void wait(semaphore S){S.value--;if(S.value < 0){block(S.L);//阻塞原语,将当前进程挂载到当前semaphore的阻塞队列}}//进程使⽤完资源后,通过signal原语释放:V操作void signal(semaphore S){S.value++;if(S.value <= 0){wakeup(S.L);//唤醒原语,将当前semaphore的阻塞队列中的第⼀个进程唤醒}}full.value=0; //缓冲区 “产品”资源数(初始为0),⽤于实现⽣产者与消费者进程的同步empty.value=n; //缓冲区 “空位”资源数(初始为n),⽤于实现⽣产者与消费者进程的同步mutex.value=1; //互斥信号量,⽤于实现所有进程之间互斥地访问缓冲区//⽣产者producer(){while(1){Produce(); //⽣产“产品”P(empty); //“空位”数-1P(mutex); //临界区上锁Storage(); //摆放产品V(mutex); //临界区解锁V(full); //“产品”数+1}}//消费者consumer(){while(1){P(full); //“产品”数-1P(mutex); //临界区上锁TakeOut(); //拿⾛产品V(mutex); //临界区解锁V(empty); //“空位”数+1Use(); //使⽤“产品”}}对于各个操作顺序的理解:1. 对于⼀部分操作的顺序,我们很好理解,符合我们的认知://⽣产者Produce(); //⽣产产品P(empty); //“空位”数-1,可能有⼈在这⾥会问这个操作为什么不可以放在“Storage甚⾄是V(full)”后⾯,考虑⼀种情况:当空位数为0时,我们是不能摆放产品的,⽽这个操作正是在检查是否还有“空位”这种资源;所以它⼀定在Storage前⾯ Storage(); //摆放产品V(full); //“产品”数+1,可能有⼈在这⾥会问这个操作为什么不可以放在“Storage甚⾄是P(empty)”前⾯,考虑⼀种情况:当产品数为n时,我们是不能再摆放产品的,因为缓冲区已满,再向其中添加数据(执⾏Storage)是要出问题的;所 //消费者P(full); //“产品”数-1,同上⾯⼀样,可能有⼈在这⾥会问这个操作为什么不可以放在“TakeOut甚⾄是V(empty)”后⾯,考虑⼀种情况:当产品数为0时,我们是不能拿⾛产品的,⽽这个操作正是在检查是否还有“产品”这种资源;所以它⼀定 TakeOut(); //拿⾛产品V(empty); //“空位”数+1,同上⾯⼀样,可能有⼈在这⾥会问这个操作为什么不可以放在“TakeOut甚⾄是P(full)”前⾯,考虑⼀种情况:当空位数为n时,我们是不能拿⾛产品的,因为缓冲区已经空了,再拿⾛(执⾏TakeOut)拿⾛个寂寞 Use(); //使⽤“产品”2. 对于其他操作:实现同步的P操作⼀定要在实现互斥的P操作之前,为什么呢?反向分析:我们考虑若调换⽣产者上述两个P操作的顺序://⽣产者producer(){while(1){Produce(); //⽣产产品P(mutex); //临界区上锁P(empty); //“空位”数-1Storage(); //摆放产品V(mutex); //临界区解锁V(full); //“产品”数+1}}//消费者consumer(){while(1){P(full); //“产品”数-1P(mutex); //临界区上锁TakeOut(); //拿⾛产品V(mutex); //临界区解锁V(empty); //“空位”数+1Use(); //使⽤“产品”}}若此时缓冲区已经放满产品,则empty=0,full=n⽣产者进程执⾏P(mutex),mutex变为0,由于empty为0即没有“空位”了,需要⽣产者进程阻塞,等待消费者拿⾛产品切换⾄消费者进程,消费者进程执⾏到P(mutex),由于mutex为0即⽣产者未释放临界资源,需要⽣产者释放临界资源,消费者进程阻塞互相等待,进⼊死锁结论:不要让因同步引起的进程阻塞(P操作可能产⽣结果)发⽣在为临界区上锁之后,因为:1. 临界区上锁,表⽰临界资源已被占⽤;若对临界区未解锁之前,发⽣了因同步引起的进程阻塞(上例中即需要⽣产者进程阻塞,等待消费者拿⾛产品)。
青岛理工大学操作系统课程设计报告院(系):计算机工程学院专业:计算机科学与技术专业学生姓名:__班级:_______学号:题目:用多进程同步方法演示“生产者-消费者”问题起迄日期:设计地点:指导教师:年度第学期完成日期: 年月日一、课程设计目的本次进行操作系统课程设计的主要任务是设计一个模拟生产者消费者工作的系统。
这个问题中有一种生产者和一种消费者,生产者和消费者对同一个缓冲区进行操作,互斥的访问缓冲区。
本次课程设计的目的就是加深对多进程如何正确访问资源的认识,同时掌握信号量在互斥访问时应该如何正确有效地使用。
掌握生产者消费者问题的解决流程和方法,提高编程能力、解决问题的能力和查阅文档的能力。
二、课程设计内容与要求1、设计目的:通过研究Linux的进程同步机制和信号量,实现生产者消费者问题的并发控制。
2、说明:有界缓冲区内设有20个存储单元,放入取出的产品设定为20个100以内的随机整数。
3、设计要求:1)生产者与消费者均有二个以上2)生产者和消费者进程的数目在程序界面上可调,在运行时可随时单个增加与减少生产者与消费者3)生产者的生产速度与消费者的消费速度均可在程序界面调节,在运行中,该值调整后立即生效4)生产者生产的产品由随机函数决定5)多个生产者或多个消费者之间必须有共享对缓冲区进行操作的函数代码6)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前生产者与消费者的指针位置,以及生产者和消费者线程标识符7)采用可视化界面,可在运行过程中随时暂停,查看当前生产者、消费者以及有界缓冲区的状态三、系统分析与设计1、系统分析系统分析1.此次课程设计的任务是生产者消费者问题的模拟演示,需要处理的数据有:生产者进程数目,消费者进程数目,生产者生产速度,消费者消费速度,缓冲区中产品的个数,以及生产、消费产品的指针。
2.程序中需要缓冲区中的信息可以动态演示,生产者、消费者的个数以及生产、消费时的速度可以随时调节,同时为了使程序更加友好,应该具有开始、暂停、停止等相关可操作按钮。
第一章、概述1.1 课题背景在多道程序环境下,进程同步问题十分重要,也是一个相当有趣的问题,因而吸引了不少学者对它进行研究,并由此而产生了一系列经典的进程同步问题。
其中比较有代表性的有“生产者—消费者问题” 、“读者—写者问题” 、“哲学家进餐问题”等等。
通过对这些问题的研究和学习,可以帮助我们更好地理解进程同步概念及实现方法。
1.2生产者—消费者问题生产者—消费者问题(Producer_consumer)是一个经典的进程同步问题。
它描述的是:有一群生产者进程在生产产品,并将此产品提供给消费者进程去消费。
为使生产者进程和消费者进程能并发执行,在它们之间设置有个缓冲区的缓冲池,生产者进程可将它所生产的产品放入一个缓冲区中,消费者进程可从一个缓冲区取得一个产品消费。
尽管所有的生产者进程和消费者进程都是以异步的方式运行的,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装有消息尚未被取走产品的缓冲区投放产品。
如下图所示:1.3进程同步机制在中引入进程后,虽然提高了资源的利用率和系统的吞吐量,但由于进程的异步性,也会给系统造成混乱,尤其是在它们争用临界资源的时候。
例如,当多个进程去争用一台打印机时,有可能使多个进程的输出结果交织在一起,难于区分;而当多个进程去争用共享变量,表格,链表时,有可能使数据处理出错。
进程同步的主要任务就是使并发执行的诸进程之间能有效地共享资源和相互合作,从而使程序的执行具有可再现性。
1.4进程同步优点进程同步其优点在于能够让操作系统更加有效地对资源进行管理和调度,最大潜力地发挥处理机的性能。
让系统的执行更加畅通无阻,尽可能地让系统少出现一些由于系统资源分配不合理所带来的死锁、死机之类的事情的发生。
保持了处理机的高速运行之后从用户角度来说程序运行所花费的时间就会更短。
从而保证了处理机在相同的时间内有更大的吞吐量。
而把并发进程的同步和互斥问题一般化,就可以得到一个抽象的一般模型,即本次课程设计的任务:生产者—消费者问题。
unix系统中同步问题和互斥问题例子同步问题和互斥问题是在多进程或者多线程编程中经常遇到的共享资源管理问题。
在Unix系统中,同步问题和互斥问题具体体现在进程间共享的文件、共享内存和信号量等资源的访问过程中。
一、同步问题同步问题指的是多个进程或线程需要按照一定的次序执行,以实现特定的功能或保证数据的一致性。
以下是一些在Unix系统中常见的同步问题例子:1.多进程文件写入在多个进程同时对同一个文件进行写入操作时,可能会出现数据混乱的问题。
例如,两个进程同时向同一个文件写入一段数据,如果操作不加以控制,可能会导致两个进程的数据交错。
为了解决这一问题,可以使用文件锁(flock)或者互斥锁(mutex)来实现对文件的互斥访问,保证每个进程对文件的独占写入操作。
2.生产者和消费者问题生产者和消费者问题是一种经典的同步问题,常用于描述多个进程或线程之间的协作关系。
在Unix系统中,可以通过共享内存、信号量等机制来实现生产者和消费者之间的同步。
例如,一个进程负责生产数据,另一个进程负责消耗数据,通过信号量来控制两个进程之间的同步,保证数据的正确交换和处理。
3.进程间通信在Unix系统中,进程间通信(IPC)是一种常见的同步问题。
例如,两个进程需要完成某个任务,但是任务的执行需要依赖于另一个进程的结果。
可以通过管道、套接字或者共享内存等方式来实现进程间的通信,保证同步和协作的顺利进行。
二、互斥问题互斥问题是指多个进程或线程对共享资源的访问需要互斥进行,以避免数据竞争和冲突。
以下是一些在Unix系统中常见的互斥问题例子:1.临界区问题临界区问题是指多个进程或线程对共享资源的访问需要互斥进行。
在Unix系统中,可以使用互斥锁(mutex)来实现对临界区的互斥访问。
例如,多个线程对共享变量进行读写操作,通过互斥锁的加锁和解锁操作来保证每次只有一个线程能够访问临界区,避免数据竞争和冲突。
2.信号量问题信号量是一种常见的同步机制,可用于解决多个进程或线程对共享资源的互斥访问问题。
实验二经典的生产者—消费者问题一、目的实现对经典的生产者—消费者问题的模拟,以便更好的理解经典进程同步问题。
二、实验内容及要求编制生产者—消费者算法,模拟一个生产者、一个消费者,共享一个缓冲池的情形。
1、实现对经典的生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。
生产者-消费者问题是典型的PV操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。
缓冲池被占用时,任何进程都不能访问。
2、每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。
在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。
他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。
三、生产者和消费者原理分析在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品被生产出来。
四、生产者与消费者功能描述:生产者功能描述:在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
消费者功能描述:消费者线程从缓冲区获得物品,然后释放缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
五、实验环境操作系统环境:Windows系统。
编程语言:C#。
六、生产者与消费者的思路和设计1、程序流程图(1) 生产者.(2) 消费者2、主要程序代码//初始化变量private void Form1_Load(object sender, EventArgs e){mutex = 1; //互斥信号量full = 0; //缓冲池中满缓冲区的数量empty = 5;//缓冲池中空缓冲区的数量count1 = 0;//生产的产品数目i = 0;lb_mutex.Text = "1";lb_full.Text = "0";lb_empty.Text = "5";}//消费者从缓冲区中消费一个产品private void consumer_Click(object sender, EventArgs e){if (full > 0){ //消费者已进入互斥临界区if (mutex == 1) //申请进入临界区{mutex = 0; //消费者已进入互斥临界区lb_mutex.Text = "0";timer_consumer.Enabled = true;//启动消费者消费缓冲区产品}else{MessageBox.Show("缓冲区被占用,请等待。
经典同步互斥之生产者—消费者问题生产者—消费者同步问题其实际上就是生活中同步、互斥问题的一个抽象模型,如多个进程合作解决文件打印的问题,汽车行驶过程中司机与售票员的活动问题,理发师理发问题等等。
要解决同步互斥问题,最主要的是理清楚活动者之间的同步关系,还有某些问题中变量的互斥问题。
分析清楚之后就是设置信号量,设置几个,并且根据实际情况给出信号量的初值。
生产者—消费者问题就是生产者进程向消费者进程提供消息。
生产者生产商品存入空缓冲区内,而消费者从缓冲区内取出产品并消费。
1、一个生产者P和一个消费者Q(其中只有同步问题)其同步关系为:(1)P进程不能向“满”的缓存区内存放产品,即仅当有一个空缓存区时才能放产品,设置信号量empty,初值为0,用于指示空缓存区数目。
(2)Q进程不能从空的缓存区中取产品,设置信号量full,初值为0,用于指示满缓存区的数目。
注意:a)在P、V操作中,P、V操作必须成对出现;b)在互斥关系中P、V操作在同一进程内;【c)在同步关系中P、V操作在不同的进程内。
其同步问题解决如下:P: //生产者repeat生产一个产品;送产品到缓冲区;V(full);//释放一个满的缓冲区;P(empty); //申请一个空的缓冲区存放产品;until false;;Q: //消费者repeatP(full);//申请一个满的缓存区取产品从缓存区取产品;V(empty);//产品取完后释放掉该空的缓存区消费产品;until false;2、多个生产者和多个消费者多个生产者和消费者问题中,缓存区属于临界资源,它只允许一个生产者放入产品或者一个消费者从中取产品。
生产者之间、生产者与消费者之间、消费者之间都必须互斥的使用缓冲区。
其中既存在同步问题,又存在互斥问题。
其同步关系为:(1)>(2)至少有一个缓冲区已存入消息后,消费者才能从中提取消息,否则消费者必须等待。
设置信号量empty,初值为n,用于指示空缓冲区的数目;(3)至少有一个缓存区是空的,生产者才能将消息存入缓冲区,否则生产者必须等待。
学习中心:专业:年级:年春/秋季学号:学生:题目:进程同步与互斥生产者-消费者问题1.谈谈你对本课程学习过程中的心得体会与建议?转眼间,学习了一个学期的计算机操作系统课程即将结束。
在这个学期中,通过老师的悉心教导,让我深切地体会到了计算机操作系统的一些原理和具体操作过程。
在学习操作系统之前,我只是很肤浅地认为操作系统只是单纯地讲一些关于计算机方面的操作应用,并不了解其中的具体操作过程和实用性。
通过这一学期的学习,我才知道操作系统(Operating System,简称OS)是管理计算机系统的全部硬件资源包括软件资源及数据资源;控制程序运行;改善人机界面;为其它应用软件提供支持等,使计算机系统所有资源最大限度地发挥作用,为用户提供方便的、有效的、友善的服务界面。
操作系统这门课程并不是教你如何使用操作系统的,而是讲操作。
总而言之,操作系统的一些原理在生活中都可以找到相应的例子。
结合生活中的例子,可以化抽象为具体,我们会更加清楚地了解到其原理与操作过程。
我觉得通过我们的不断学习,结合生活中的实际问题,我们就会把操作系统学得更好。
总体来说,通过这次的对操作系统的总结,有收获也有遗憾、不足的地方,但我想,我已经迈入了操作系统的大门,只要我再认真努力的去学习,去提高,肯定能让自己的知识能力更上一层楼.1设计思路及主要代码分析1.1设计思路在这次设计中定义的多个缓冲区不是环形循环的,并且不需要按序访问。
其中生产者可以把产品放到某一个空缓冲区中,消费者只能消费被指定生产者生产的产品。
本设计在测试用例文件中指定了所有生产和消费的需求,并规定当共享缓冲区的数据满足了所有有关它的消费需求后,此共享才可以作为空闲空间允许新的生产者使用。
本设计在为生产者分配缓冲区时各生产者之间必须互斥,此后各个生产者的具体生产活动可以并发。
而消费者之间只有在对同一个产品进行消费时才需要互斥,它们在消费过程结束时需要判断该消费者对象是否已经消费完毕并释放缓冲区的空间。
课程设计报告课程名称:操作系统实验题目:用多进程同步方法解决生产者-消费者问题院系:计算机科学与工程学院班级:姓名:学号:指导老师:一、概述:1、问题描述:用多进程同步方法解决生产者-消费者问题设计目的:通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制.说明:有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数.设计要求:1) 每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者线程的标识符.2) 生产者和消费者各有两个以上.3) 多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码.2、程序设计基本思想:生产者—消费者问题是一种同步问题的抽象描述。
计算机系统中的每个进程都可以消费或生产某类资源。
当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
而当某个进程释放资源时,则它就相当一个生产者。
一个有限空间的共享缓冲区,负责存放货物。
生产者向缓冲区中放物品,缓冲区满则不能放。
消费者从缓冲区中拿物品,缓冲区空则不能拿。
因为有多个缓冲区,所以生产者线程没有必要在生成新的数据之前等待最后一个数据被消费者线程处理完毕。
同样,消费者线程并不一定每次只能处理一个数据。
在多缓冲区机制下,线程之间不必互相等待形成死锁,因而提高了效率。
多个缓冲区就好像使用一条传送带替代托架,传送带上一次可以放多个产品。
生产者在缓冲区尾加入数据,而消费者则在缓冲区头读取数据。
当缓冲区满的时候,缓冲区就上锁并等待消费者线程读取数据;每一个生产或消费动作使得传送带向前移动一个单位,因而,消费者线程读取数据的顺序和数据产生顺序是相同的。
可以引入一个count计数器来表示已经被使用的缓冲区数量。
用Producer和Consumer 来同步生产者和消费者线程。
每当生产者线程发现缓冲区满( count=BufferSize ),它就等待Consumer事件。
⽣产者-消费者问题(进程同步问题)最近在学线程,在加上操作系统也在学线程,于是乎有了这篇⽂章问题描述:⼀群⽣产者进程在⽣成产品,并将这些产品提供给消费者进程去消费. 他们之间有⼀个公共的缓冲区⽤来存放产品,当产品为空时消费者不能消费,当产品为满时⽣产者不能⽣产CPP实现利⽤mutex 互斥量来对缓存区的操作进⾏加锁#include <chrono>#include <iostream>#include <mutex>#include <thread>constexpr int n = 10; // 缓存区⼤⼩int in = 0, out = 0; // ⽣产指针,消费指针int full = 0, empty = 10; // 空与满int buffer[10]; // 缓存区std::mutex mtx; // 互斥量/*** ⽣产者函数*/void producer() {do {while (full == n);std::this_thread::sleep_for(std::chrono::seconds(1));{std::scoped_lock lock(mtx);buffer[in] = 1;in = (in + 1) % n;std::cout << "⽣产者⽣产:" << in << "\n";empty--;full++;}} while (true);}/*** 消费者函数*/void consumer() {do {while (empty == n);{std::scoped_lock lock(mtx);buffer[out] = 0;out = (out + 1) % n;std::cout << "消费者消费:" << out << "\n";empty++;full--;}std::this_thread::sleep_for(std::chrono::seconds(2));} while (true);}int main() {std::thread t1{producer};std::thread t2{consumer};t1.join();t2.join();return 0;}Java实现⽤Storage对象模拟缓存区,关键代码如下/*** 存储类*/public class Storage {private Product[] products = new Product[10];private int top = 0;public synchronized void push(Product product){while(top == products.length){try{System.out.println("producer wait");wait(); //缓冲区满,⽆法⽣产,则阻塞}catch (InterruptedException e){e.printStackTrace();}}products[top++] = product;System.out.println(Thread.currentThread().getName()+" ⽣产了 "+product); System.out.println("producer notifyAll");notifyAll(); //⽣产出新的产品,唤醒消费者进程}public synchronized Product pop(){while (top==0){try{System.out.println("consumer wait");;wait(); //缓冲区空,⽆法消费,阻塞}catch (InterruptedException e){e.printStackTrace();}}--top;Product p = new Product(products[top].getId(),products[top].getName()); products[top] = null;System.out.println(Thread.currentThread().getName()+ " 消费了 "+p);System.out.println("consumer notifyAll");notifyAll(); //消费了产品,唤醒⽣产者return p;}}public class Producer implements Runnable{private Storage storage;public Producer(Storage storage){this.storage = storage;}@Overridepublic void run() {int i=0;Random r = new Random();while(i<10){i++;Product product = new Product(i,"电话"+r.nextInt(100));storage.push(product);}}}public class Consumer implements Runnable{private Storage storage;public Consumer(Storage storage){this.storage = storage;}@Overridepublic void run() {int i=0;while (i<10){i++;storage.pop();try {Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();} } }}。
第二章进程管理(三)进程同步5、经典同步问题1、生产者—消费者问题生产者消费者问题是一种同步问题的抽象描述。
计算机系统中的每个进程都可以消费(使用)或生产(释放)某类资源。
这些资源可以是硬件资源,也可以是软件资源。
当某一进程使用某一资源时,可以看作是消费,称该进程为消费者。
而当某一进程释放某一资源时,它就相当于生产者。
问题1:设某计算进程CP和打印进程IOP共用一个单缓冲区,CP进程负责不断地计算数据并送入缓冲区T中,IOP进程负责不断地从缓冲区T中取出数据去打印。
通过分析可知,CP、IOP必须遵守以下同步规则:(1)当CP进程把计算结果送入缓冲区时,IOP进程才能从缓冲区中取出结果去打印;(2)当IOP进程把缓冲区中的数据取出打印后,CP进程才能把下一个计算结果送入缓冲区.(3)为此设有两个信号量Sa=0,Sb=1,Sa表示缓冲区中有无数据,Sb表示缓冲区中有无空位置。
两个进程的同步可以描述如下:问题2:一组生产者通过具有N个缓冲区的共享缓冲池向一组消费者提供数据。
问题分析”:为解决生产者消费者问题,应该设两个同步信号量,一个说明空缓冲区的数目,用empty表示,初值为有界缓冲区的大小N,另一个说明已用缓冲区的数目,用full表示,初值为0。
由于在此问题中有M个生产者和N个消费者,它们在执行生产活动和消费活动中要对有界缓冲区进行操作。
由于有界缓冲区是一个临界资源,必须互斥使用,所以,另外还需要设置一个互斥信号量mutex,其初值为1。
问题的解:注意:在每个程序中用于实现互斥的P(mutex)和V(mutex)必须成对的出现对资源信号量empty和full的P和V操作,同样需要成对地出现,但它们分别处于不同的程序中。
在每个程序中的多个P操作顺序不能颠倒。
先同步后互斥。
生产者进程缓冲池消费者进程1┇┇i┇┇2、哲学家就餐问题有五个哲学家围坐在一圆桌旁,桌中央有一盘通心粉,每人面前有一只空盘子,每两人之间放一只筷子。
进程同步:⽣产者消费者模型以及解决⽅法背景⽣产者和消费者问题是线程模型中的经典问题:⽣产者和消费者在同⼀时间段内共⽤同⼀个存储空间,⽣产者往存储空间中添加产品,消费者从存储空间中取⾛产品,当存储空间为空时,消费者阻塞,当存储空间满时,⽣产者阻塞。
为什么要使⽤⽣产者和消费者模式:在线程世界⾥,⽣产者就是⽣产数据的线程,消费者就是消费数据的线程。
在多线程开发当中,如果⽣产者处理速度很快,⽽消费者处理速度很慢,那么⽣产者就必须等待消费者处理完,才能继续⽣产数据。
同样的道理,如果消费者的处理能⼒⼤于⽣产者,那么消费者就必须等待⽣产者。
为了解决这个问题,于是引⼊了⽣产者和消费者模式。
⽣产者——消费者模型会遇到的问题⽣产者——消费者模型中,⽣产者和消费者线程之间需要传递⼀定量的数据,两个线程会使⽤⼀个特定⼤⼩的共享环形缓冲器。
⽣产者向缓冲器中写⼊数据,直到它到达缓冲器的终点;然后它会再次从起点重新开始,覆盖已经存在的数据。
消费者线程则会读取⽣成的数据。
在⽣产者——消费者实例中,对于同步的需求有两个部分:1.如果⽣产者线程⽣成数据的速度太快,那么将会把消费者线程还没有读取的数据覆盖;2.如果消费者线程读取数据的速度过快,那么它就会越过⽣产者线程⽽读取⼀些垃圾数据。
⽣产者——消费者模型解决⽅法:容易导致死锁的实现:让⽣产者线程填满缓冲器,然后等待消费者线程读取完缓冲器中全部数据。
使⽤2个信号量解决单消费者单⽣产者的问题使⽤两个信号量:freeSpace 与 usedSpacefreeSpace 信号量控制⽣产者线程写⼊数据的那部分缓冲器, usedSpace 信号量则控制消费者线程读取数据的那部分缓冲器区域。
这两个区域是相互补充的。
常⽤缓冲区容量值初始化 freeSpace 信号量,意味着它最多可以获取的缓冲器资源量。
在启动这个应⽤程序时,消费者线程就会获得⾃由的字节并把它们转换为⽤过的字节。
⽤0初始化usedSpace信号量,以确保消费者线程不会在⼀开始就读取到垃圾数据。