版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
实验题目生产者和消费者实验实验目的通过对“生产者-消费者”问题编程实现,了解线程创建、同步信号量、互斥信号量、临界区的创建和使用,初步了解并发程序设计方法。实验内容“生产者-消费者问题模型是指一组生产者进程和一组消费者进程通过一个缓冲区进行合作。先有生产者生产产品,再有消费者消费生产者生产的产品。本实验以“生产者-消费者”模型为依据,提供了一个多线程“生产者-消费者”实例,要求读者分析该实例,调试并得出最终结果。分析该结果,得相应结论。设计思路和算法主要数据结构及其说明InitializeCriticalSection()函数函数功能:初始化一个临界资源对象CreateSemaphore()函数函数功能:创建一个同步信号灯SemaphoreCreateMutex()函数函数功能:创建一个互斥信号灯MutexCreateThread()函数函数功能:创建一线程WaitForSingleObject()函数函数功能:有信号量时执行,否则一直等待测试数据设计及测试结果分析输入文本缓冲区数线程序号线程标识延时时间消费顺序由test1到达的时间知:线程执行的顺序是637(消费产品1,无1,等待)217(有产品1,消费,消费产品3,有3,消费,消费产品2,有2,消费)4(消费产品5,无5,等待)54(有产品5,消费,消费产品6,有6消费)程序能正常执行至结束由test3到达时间及缓冲区数量知6,3,8(消费产品1,无1,等待),2,7,,5(无缓冲区不生产,找消费者消费),4(消费产品5,无5,等待)1(无缓冲区不生产,找消费者消费)程序形成死锁,可调整执行顺序或者增加缓冲区消除死锁程序运行结果test1运行结果:test3运行结果:实验体会在有限的缓冲区里,生产者生产的产品要有消费者来消费,使缓冲区一直保持在可用状态,若是安排不合理,则会陷入死循环。一般上,解决的办法一是调度算法合理,即线程到达的顺序,二是安排足够大的缓冲区。生产者线程和消费者线程共用一个缓冲池时,生产者生产产品占用缓冲区,消费者消费产品释放缓冲区,要使变量之间的数传递。系统对这两个函数执行的过程使用的是并发执行,即在执行过程中跳过这段程序转去执行另一段并发程序,回过头来再执行起初尚未执行完的那段程序。这次实验让我们看到了并发程序执行的过程。附源程序文件#include<windows.h>#include<fstream.h>#include<stdio.h>#include<string>#include<conio.h>//定义一些常量#defineMAX_BUFFER_NUM20//本程序允许的最大临界区间#defineINTE_PER_SEC1000//秒到毫秒的乘法因子#defineMAX_THREAD_NUM64//本程序允许的生产者和消费者线程的总数//定义一个结构,记录在测试文件中指定的每一个线程的参数structThreadInfo{ intserial;//线程序列号 charentity; doubledelay;//线程延迟 intthread_request[MAX_THREAD_NUM];//线程请求队列 intn_request;//请求个数};//全局变量CRITICAL_SECTIONPC_Critical[MAX_BUFFER_NUM];//临界区对象的声明,用于管理缓冲区的互斥访问intBuffer_Critical[MAX_BUFFER_NUM];//缓冲区声明,用于存放产品HANDLEh_Thread[MAX_THREAD_NUM];//用于存储每个线程句柄的数组ThreadInfoThread_Info[MAX_THREAD_NUM];//线程信息数组HANDLEempty_semaphore;//一个信号量HANDLEh_mutex;//一个互斥量DWORDn_Thread=0;//实际的线程数目DWORDn_Buffer_or_Critical;//实际的缓冲区或者临界区数目HANDLEh_Semaphore[MAX_THREAD_NUM];//生产者允许消费者开始消费的信号量//生产消费及辅助函数的声明voidProduce(void*p);voidConsume(void*p);boolIfInOtherRequest(int);intFindProducePosition();intFindBufferPosition(int);intmain(void){ //声明所需变量 DWORDwait_for_all; ifstreaminFile; //初始化缓冲区 for(inti=0;i<MAX_BUFFER_NUM;i++) Buffer_Critical[i]=-1; //初始化每个线程的请求队列 for(intj=0;j<MAX_THREAD_NUM;j++){ for(intk=0;k<MAX_THREAD_NUM;k++) Thread_Info[j].thread_request[k]=-1; Thread_Info[j].n_request=0; } //初始化临界区 for(i=0;i<MAX_BUFFER_NUM;i++) InitializeCriticalSection(&PC_Critical[i]); //打开输入文件,按照规定的格式提取线程等信息 inFile.open("test3.txt"); //从文件中获取实际的缓冲区的数目 inFile>>n_Buffer_or_Critical; inFile.get(); //显示获得缓冲区的数目信息 printf("输入文件是:\n"); printf("%d\n",(int)n_Buffer_or_Critical); //提取每个现成的信息到相应的数据结构中 while(inFile){ inFile>>Thread_Info[n_Thread].serial; inFile>>Thread_Info[n_Thread].entity; inFile>>Thread_Info[n_Thread].delay; charc; inFile.get(c); while(c!='\n'&&!inFile.eof()){ inFile>>Thread_Info[n_Thread].thread_request[Thread_Info[n_Thread].n_request++]; inFile.get(c); } n_Thread++; } //显示获得的线程信息,便于确认正确性 for(j=0;j<(int)n_Thread;j++){ intTemp_serial=Thread_Info[j].serial; charTemp_entity=Thread_Info[j].entity; doubleTemp_delay=Thread_Info[j].delay; printf("\nthread%2d%c%f",Temp_serial,Temp_entity,Temp_delay); intTemp_request=Thread_Info[j].n_request; for(intk=0;k<Temp_request;k++) printf("%d",Thread_Info[j].thread_request[k]); cout<<endl; } printf("\n\n"); //创建在模拟过程中几个必要的信号量 empty_semaphore=CreateSemaphore(NULL,n_Buffer_or_Critical,n_Buffer_or_Critical,"semaphor_for_empty"); h_mutex=CreateMutex(NULL,FALSE,"mutex_for_update"); //下面的这个循环用线程的ID号来为相应生产线程的产品续写时所使用的同步信号量命名 for(j=0;j<(int)n_Thread;j++){ std::stringlp="semaphore_for_produce_"; inttemp=j; while(temp){ charc=(char)(temp%10); lp+=c; temp/=10; } h_Semaphore[j+1]=CreateSemaphore(NULL,0,n_Thread,lp.c_str()); } //创建生产者和消费者线程 for(i=0;i<(int)n_Thread;i++){ if(Thread_Info[i].entity=='p') h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Produce),&(Thread_Info[i]),0,NULL); else h_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consume),&(Thread_Info[i]),0,NULL); } //主程序等待各个线程的动作结束 wait_for_all=WaitForMultipleObjects(n_Thread,h_Thread,TRUE,-1); printf("\n\n全部生产者和消费者都已完成他们的工作\n"); printf("按任意键返回!\n"); _getch(); return0;}//确认是否还有对同一产品的消费请求未执行boolIfInOtherRequest(intreq){ for(inti=0;i<n_Thread;i++) for(intj=0;j<Thread_Info[i].n_request;j++) if(Thread_Info[i].thread_request[j]==req) returnTRUE; returnFALSE; }//找出当前可以进行产品的空缓冲区位置intFindProducePosition(){ intEmptyPosition; for(inti=0;i<n_Buffer_or_Critical;i++) if(Buffer_Critical[i]==-1){ EmptyPosition=i; //用下面这个特殊值表示缓冲区正处于被写状态 Buffer_Critical[i]=-2; break; } returnEmptyPosition;}//找出当期所需生产者生产的产品位置intFindBufferPosition(intProPos){ intTempPos; for(inti=0;i<n_Buffer_or_Critical;i++) if(Buffer_Critical[i]==ProPos){ TempPos=i; break; } returnTempPos;}//生产者进程voidProduce(void*p){ //局部变量声明 DWORDwait_for_semaphore,wait_for_mutex,m_delay; intm_serial; //获得本线程的信息 m_serial=((ThreadInfo*)(p))->serial; 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); intProducePos=FindProducePosition(); ReleaseMutex(h_mutex); //生产者在获得自己的空位置并做上标记后,以下是我写操作在生产者之间可以并发 //核心生产步骤中,程序将生产者的ID作为产品编号放入,方便消费者识别 printf("生产者%2d开始在缓冲区%2d生产产品.\n",m_serial,ProducePos); Buffer_Critical[ProducePos]=m_serial; printf("生产者%2d完成生产过程:\n",m_serial); printf("缓冲区[%2d]:%3d\n",ProducePos,Buffer_Critical[ProducePos]); //使生产者写的缓冲区可以被多个消费者使用,实现读写同步 ReleaseSemaphore(h_Semaphore[m_serial],n_Thread,NULL);}//消费者进程voidConsume(void*p){ //局部变量 DWORDwait_for_semaphore,m_delay; intm_serial,m_requestNum;//消费者的序列号和请求的数目 intm_thread_request[MAX_THREAD_NUM];//本消费线程的请求队列 //提取本线程的信息到本地 m_serial=((ThreadInfo*)(p))->serial; m_delay=(DWORD)(((ThreadInfo*)(p))->delay*INTE_PER_SEC); m_requestNum=((ThreadInfo*)(p))->n_request; for(inti=0;i<m_requestNum;i++) m_thread_request[i]=((ThreadInfo*)(p))->thread_request[i]; Sleep(m_delay); //循环进行所需产品的消费 for(i=0;i<m_requestNum;i++){ //请求消费下一个产品 printf("消费者%2d请求消费%2d产品.\n",m_serial,m_thread_request[i]); //如果对应生产者没有生产,则等待;如果生产了,允许的消费者数目-1,实现了读写同步 wait_for_semaphore=WaitForSingleObject(h_Semaphore[m_thread_request[i]],-1); //查询所需产品放到缓冲区的号 intBufferPos=FindBufferPosition(m_thread_requ
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年洗车场绿色环保技术与设备转让合同3篇
- 2024版精密机房建造协议条款版
- 2024聘请教练合同
- 二零二四平面模特演艺事业聘用合同-影视界签约范本9篇
- 2024版设备进口采购协议中英文版版B版
- 2024门窗安装安全协议与合同书
- 2025年度铝合金门窗行业绿色建筑认证合同4篇
- 2025年版IT咨询服务合同样本6篇
- 二零二四南京租房合同家具家电使用及维修协议3篇
- 2024英伦游学夏令营境外紧急联络与协助服务合同3篇
- 2025年度土地经营权流转合同补充条款范本
- 南通市2025届高三第一次调研测试(一模)地理试卷(含答案 )
- 2025年上海市闵行区中考数学一模试卷
- 2025中国人民保险集团校园招聘高频重点提升(共500题)附带答案详解
- 0的认识和加、减法(说课稿)-2024-2025学年一年级上册数学人教版(2024)001
- 重症患者家属沟通管理制度
- 医院安全生产治本攻坚三年行动实施方案
- 法规解读丨2024新版《突发事件应对法》及其应用案例
- 信息安全意识培训课件
- Python试题库(附参考答案)
- 成都市国土资源局关于加强国有建设用地土地用途变更和
评论
0/150
提交评论