进程同步机制与互斥-生产者消费者问题_第1页
进程同步机制与互斥-生产者消费者问题_第2页
进程同步机制与互斥-生产者消费者问题_第3页
进程同步机制与互斥-生产者消费者问题_第4页
进程同步机制与互斥-生产者消费者问题_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

学习中心: 专 业: 年 级: 年 春/秋 季 学 号: 学 生: 题 目:进程同步与互斥 生产者-消费者问题 1.谈谈你对本课程学习过程中的心得体会与建议? 转眼间,学习了一个学期的计算机操作系统课程即将结束。在这个学期中,通过老师的悉心教导,让我深切地体会到了计算机操作系统的一些原理和具体操作过程。在学习操作系统之前,我只是很肤浅地认为操作系统只是单纯地讲一些关于计算机方面的操作应用,并不了解其中的具体操作过程和实用性。通过这一学期的学习,我才知道操作系统(Operating System,简称OS)是管理计算机系统的全部硬件资源包括软件资源及数据资源;控制程序运行;改善人机界面;为其它应用软件提供支持等,使计算机系统所有资源最大限度地发挥作用,为用户提供方便的、有效的、友善的服务界面。操作系统这门课程并不是教你如何使用操作系统的,而是讲操作。总而言之,操作系统的一些原理在生活中都可以找到相应的例子。结合生活中的例子,可以化抽象为具体,我们会更加清楚地了解到其原理与操作过程。我觉得通过我们的不断学习,结合生活中的实际问题,我们就会把操作系统学得更好。总体来说,通过这次的对操作系统的总结,有收获也有遗憾、不足的地方,但我想,我已经迈入了操作系统的大门,只要我再认真努力的去学习,去提高,肯定能让自己的知识能力更上一层楼. 1 设计思路及主要代码分析1.1设计思路在这次设计中定义的多个缓冲区不是环形循环的,并且不需要按序访问。其中生产者可以把产品放到某一个空缓冲区中,消费者只能消费被指定生产者生产的产品。本设计在测试用例文件中指定了所有生产和消费的需求,并规定当共享缓冲区的数据满足了所有有关它的消费需求后,此共享才可以作为空闲空间允许新的生产者使用。本设计在为生产者分配缓冲区时各生产者之间必须互斥,此后各个生产者的具体生产活动可以并发。而消费者之间只有在对同一个产品进行消费时才需要互斥,它们在消费过程结束时需要判断该消费者对象是否已经消费完毕并释放缓冲区的空间。1.2程序流程图生产者消费者主函数NN存在空缓冲区?有消费请求?初始化缓冲区,消费请求队列及部分同步对象YYNY另一生产者正在生产?NY此请求可满足?提取线程信息进入临界区(所有生产者之间互斥)确定产品位置完成线程相关同步对象的初始化Y此产品正被消费?N从空缓冲区中为本生产者的产品分配一个空间进入临界区(对同一产品进行请求的消费者之间互斥)创建线程模拟生产和消费退出临界区等待所有线程结束消费产品、并判断是否应该释放产品所占缓冲区在该缓冲区放入产品程序结束退出临界区通过信号量通知等待本产品的消费者结束消费进程结束生产进程1.3基本内容在设计程序时主要有三个主体部分、三个辅助函数和一个数据结构。其中主体部分为一个主函数main(),用于初始化缓冲区和各个同步对象,并完成线程信息的读入,最后根据该组的线程记录启动模拟线程,并等待所有线程的运行结束后退出程序;生产者函数Produce()和消费者函数Consume(),生产者和消费者函数运行于线程中完成对缓冲区的读、写动作,根据此处生产消费的模型的特点,生产者和消费者之间通过使用同步对象实现了生产和消费的同步与互斥,是本实验的核心所在。另外三个辅助性函数被生产者和消费者函数调用,是上述生产和消费函数中对缓冲区进行的一系列处理。定义一个数据结构,记录在测试文件中指定的每一个线程的参数。1) 用一个整型数组Buffer_Critical来代表缓冲区。不管是生产产品还是对已有的产品的消费都需要访问该组缓冲区。2) 进程信息ThreadInfo数据结构,包含线程的各个信息。struct ThreadInfoint serial; /线程序列号char entity; /是P还是Cdouble delay; /线程延迟int thread_requestMAX_THREAD_NUM; /线程请求队列int n_request; /请求个数;3) 在实现本程序的消费生产模型时,具体的通过如下同步对象实现互斥: 设一个互斥量h_mutex,以实现生产者在查询和保留缓冲区内的下一个位置时进行互斥。 每一个生产者用一个信号量与其消费者同步,通过设置h_SemaphoreMAX_THREAD_NUM信号量 数组实现,该组信号量用于相应的产品已产生。同时用一个表示空缓冲区数目的信号量empty_semaphore进行类似的同步,只是缓冲区中是否存在空位置,以便开始生产下一个产品。 每一个缓冲区用一个同步对象实现该缓冲区上消费者之间的互斥,这通过设置临界区对象数组PC_CrilicalMAX_BUFFER_NUM实现。1.4程序代码#include#include#include#include#include#include#define MAX_BUFFER_NUM 10 #define INTE_PER_SEC 1000#define MAX_THREAD_NUM 64 /定义一个结构,记录在测试文件中指定的每一个线程的参数struct ThreadInfo /进程信息ThreadInfo数据结构,包含线程的各个信息int serial; /线程序列号char entity; /是P还是Cint delay; /线程延迟int thread_requestMAX_THREAD_NUM; /线程请求队列 int n_request; /请求个数;/每一个缓冲区用一个同步对象实现该缓冲区上消费者之间的互斥,这通过设置临界区对象数组PC_CrilicalMAX_BUFFER_NUM实现。CRITICAL_SECTION PC_Critical MAX_BUFFER_NUM; /用一个整型数组Buffer_Critical来代表缓冲区。不管是生产产品还是对已有的产品的消费都需要访问该组缓冲区。int Buffer_CriticalMAX_BUFFER_NUM; HANDLE h_ThreadMAX_THREAD_NUM;ThreadInfo Thread_InfoMAX_THREAD_NUM;/设一个互斥量h_mutex,以实现生产者在查询和保留缓冲区内的下一个位置时进行互斥。HANDLE h_mutex; /每一个生产者用一个信号量与其消费者同步,通过设置h_SemaphoreMAX_THREAD_NUM信号量数组实现,该组信号量用于相应的产品已产生。HANDLE h_SemaphoreMAX_THREAD_NUM; /同时用一个表示空缓冲区数目的信号量empty_semaphore进行类似的同步,只是缓冲区中是否存在空位置,以便开始生产下一个产品。HANDLE empty_semaphore; DWORD n_Thread=0; DWORD n_Buffer_or_Critical;void Produce(void *p);void Consume(void *p);bool IfInOtherRuquest(int);int FindProducePosition();int FindBufferPosition(int);/函数 输入数据,提取线程信息到数据结构中,初始化临界区,创建信号量,创建线程int main(void) /声明所需变量DWORD wait_for_all;ifstream inFile;/初始化缓冲区for(int i=0;iMAX_BUFFER_NUM;i+)Buffer_Criticali=-1; /初始化每个线程的请求序列for(int j=0;jMAX_THREAD_NUM;j+)for(int k=0;kMAX_THREAD_NUM;k+)Thread_Infoj.thread_requestk=-1;Thread_Infoj.n_request=0; /初始化临界段对象for(i=0;in_Buffer_or_Critical;inFile.get();printf(输入文件是:n); /显示获得的缓冲区数目信息 printf( %d个缓冲区 n,(int)n_Buffer_or_Critical);/提取每个线程信息到相应的数据结构中while(inFile)inFileThread_Infon_Thread.serial;inFileThread_Infon_Thread.entity;inFileThread_Infon_Thread.delay;char c;inFile.get(c); while(c!=n& !inFile.eof()inFileThread_Infon_Thread.thread_requestThread_Infon_Thread.n_request+;inFile.get(c); n_Thread+; /显示获得的线程信息,便于确认正确性for(j=0;j(int)n_Thread;j+)int Temp_serial=Thread_Infoj.serial;char Temp_entity=Thread_Infoj.entity;int Temp_delay=Thread_Infoj.delay;printf( 线程%2d %c %d , Temp_serial,Temp_entity,Temp_delay);int Temp_request=Thread_Infoj.n_request;for(int k=0;kTemp_request;k+)printf( %d ,Thread_Infoj.thread_requestk);coutendl;cout-endl; empty_semaphore=CreateSemaphore(NULL,n_Buffer_or_Critical,n_Buffer_or_Critical,semaphore_for_empty);/创建在模拟过程中的几个信号量h_mutex=CreateMutex(NULL,FALSE,mutex_for_update); /用线程的ID号来为相应的生产线程的产品读写时所使用的同步信号量命名for(j=0;j(int)n_Thread;j+)std:string lp =semaphore_for_produce_;int temp=j;while(temp)/转换为字符char c=(char)(temp%10);lp+=c;temp/=10;h_Semaphorej+1=CreateSemaphore(NULL,0,n_Thread,lp.c_str();/生产者消费者线程for(i=0;i(int)n_Thread;i+) if(Thread_Infoi.entity=P)h_Threadi=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Produce),&(Thread_Infoi),0,NULL);elseh_Threadi=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consume),&(Thread_Infoi),0,NULL);/主线程等待各个线程结束wait_for_all=WaitForMultipleObjects(n_Thread,h_Thread,TRUE,-1);cout-endl; printf(所有的生产者和消费者已经完成了他们的工作。n);printf(请按任意键退出!n);_getch();return 0;/确认是否还有对同一产品的消费请求未执行bool IfInOtherRequest(int req)for(int i=0;in_Thread;i+)for(int j=0;jThread_Infoi.n_request;j+)if(Thread_Infoi.thread_requestj=req)return TRUE;return FALSE; /找出当前可以进行产品生产的空缓冲区位置;int FindProducePosition()/用下面这个特殊值表示本缓冲区正处于被写状态;int EmptyPosition;for(int i=1;i=n_Buffer_or_Critical;i+)if(Buffer_Criticali=-1)EmptyPosition=i;Buffer_Criticali=-2;break;return EmptyPosition;int FindBufferPosition(int ProPos)int TempPos;for(int i=1;iserial;m_delay=(DWORD)(ThreadInfo*)(p)-delay*INTE_PER_SEC);Sleep(m_delay);/开始请求生产printf(生产者 %2d 请求生产n,m_serial);/确认有缓冲区可以生产,同时将空位置数empty减1;用于生产者和消费者之间的同步;wait_for_semaphore=WaitForSingleObject(empty_semaphore,-1);/互斥访问下一个可用于生产的空临界区,实现写写互斥wait_for_mutex=WaitForSingleObject(h_mutex,-1);int ProducePos=FindProducePosition();ReleaseMutex(h_mutex);/生产者在获得自己的空位置并做上标记后,以下写操作在生产者之间可以并发/在核心生产步骤中,程序将生产者的ID作为产品编号放入,方便消费者识别printf(生产者 %2d 开始生产在位置 %2dn,m_serial,ProducePos);Buffer_CriticalProducePos=m_serial;printf(生产者 %2d 完成生产n,m_serial);printf(位置%2d:%3d 的产品 n,ProducePos,Buffer_Critical ProducePos);/使生产者写的缓冲区可以被多个消费者使用,实现读写同步ReleaseSemaphore(h_Semaphorem_serial,n_Thread,NULL);/消费者进程void Consume(void*p)DWORD wait_for_semaphore,m_delay;/消费者的序列号和请求的数目int m_serial,m_requestNum;/本消费线程的请求队列int m_thread_requestMAX_THREAD_NUM;/提取本线程信息到本地m_serial=(ThreadInfo*)(p)-serial;m_delay=(DWORD)(ThreadInfo*)(p)-delay*INTE_PER_SEC);m_requestNum=(ThreadInfo*)(p)-n_request;for(int i=0;ithread_requesti;Sleep(m_delay);for(i=0;ithread_requesti=-1;if(!IfInOtherRequest(m_thread_requesti)/标记缓冲区为空Buffer_CriticalBufferPos=0;printf(消费者 %2d 消费完成 %2d n,m_seri

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论