生产者,消费者问题_第1页
生产者,消费者问题_第2页
生产者,消费者问题_第3页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

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

文档简介

1、实训二 操作系统中的经典线程同步问题一、 实训目的 :1、通过对 “生产者 -消费者 ”问题编程实现,了解线程创建、同步信号量、互斥信号量、临界区 的创建和使用。2、了解线程互斥和同步机制。3、了解 PV 原语和信号量在线程互斥和同步机制中的运用。二 、实训环境: 一台 PC 机/人三、预习内容:1、进程的控制。2、进程同步。3、本实验内容主要对应于教材第 2 章中关于进程的各节四、实训内容:1、编写进程控制程序并运行,理解进程控制的各操作。2、生产者和消费者问题,本实验用到几个API 函数:CreatThread, CreatMutex, CreatSemaphore, WaitForSin

2、gleObject,ReleaseSemaphore, ReleaseMutex, InitializeCriticalSection,EnterCriticalSection, LeaveCriticalSection这些函数的作用:CreatThread: 创建一个线程,该线程在调用进程的地址空间中执CreatMutex : 产生一个命名的或者匿名的互斥量对象。WaitForSingleObject (对应 p 操作)锁上互斥锁,ReleaseMutex (对应 v 操作)打开互斥锁。CreateSemaphore:创建一个命名的或者匿名的信号对象信号量可以看作是在互斥量上的一个扩展。Wa

3、itForSingleObject :使程序处于等待状态,直到信号量(或互斥量)hHandle出现或者超过规定的等待最长时间,信号量出现指信号量大于或等于1,互斥量出现指打开互斥锁。在返回之前将信号量减 1或者锁上互斥锁。Releasesemaphore将所指信号量加上指定大小的一个量,执行成功,则返回非0值。ReleaseMutex :用来打开互斥量,即将互斥量加1。成功调用则返回0。InitializeCriticalSection :该函数初始化临界区对象。EnterCriticalSection :该函数用于等待指定临界区对象的所有权。当调用线程被赋予所有权时,该函数返回。LeaveC

4、riticalSection :该函数释放指定的临界区对象的所有权。3、测试数据设计及测试结果分析已知测试用例文件输入的文件时:thread 1 P 5.000000thread 2 P 4.000000thread 3 P 2.000000thread 4C6.00000056thread 5P7.000000thread 6P1.000000thread 7C3.000000132生产者 6发送生产请求信号.生产者6开始在缓冲区 0生产产品.生产者6完成生产过程:缓冲区【0】:6生成者3发送生产请求信号.生产者 3开始在缓冲区1 生产产品.生产者 3完成生产过程缓冲区【1】:3消费者 7请

5、求消费1 产品消费者 7请求消费1 产品生产者 2发送生成者请求信号2开始在缓冲区2生产产品生产者2完成生产过程:缓冲区【2】:2生产者 1发送生产请求信号生产者 1开始在缓冲区3生产产品.生产者 1完成生产过程:缓冲区【3】:1消费者 7开始消费 1产品消费者7成功消费1 :缓冲区【3】.:-1消费者7请求消费3产品消费者7开始消费3产品消费者7成功消费3:缓冲区【1】:-1|消费者7请求消费2产品消费者7开始消费2产品消费者7成功消费2:缓冲区【2】:-1消费者4请求消费 5产品生产者5发送生产请求信号生产者5 开始在缓冲区1生产产品生产者5 完成生产过程缓冲区【1】:5消费者4请求消费5

6、产品消费者4 请求消费5产品缓冲区【1】:-1消费者4请求消费6产品消费者4开始消费6产品消费者4成功消费6 :缓冲区【0】:-1五、参考程序#include#include#include #include#include/ 定义一些常量;/ 本程序允许的最大临界区数;#define MAX_BUFFER_NUM 10/ 秒到毫秒的乘法因子;#define INTE_PER_SEC 1000/ 本程序允许的生产和消费线程的总数;#define MAX_THREAD_NUM 64/ 定义一个结构,记录在测试文件中指定的每一个线程的参数struct ThreadInfoint serial; /

7、 线程序列号 char entity; / 是 P 还是 C double delay;/ 线程延迟int thread_requestMAX_THREAD_NUM; / 线程请求队列int n_request;/ 请求个数;/ 全局变量的定义/ 临界区对象的声明 , 用于管理缓冲区的互斥访问;CRITICAL_SECTION PC_CriticalMAX_BUFFER_NUM;int Buffer_CriticalMAX_BUFFER_NUM; / 缓冲区声明,用于存放产品;HANDLE h_ThreadMAX_THREAD_NUM; / 用于存储每个线程句柄的数组;ThreadInfoTh

8、read_InfoMAX_THREAD_NUM;/线程信息数组;HANDLEempty_semaphore;/一个信号量;HANDLEh_mutex;/一个互斥量;DWORDn_Thread = 0;/ 实际的线程的数目;DWORDn_Buffer_or_Critical;/ 实际的缓冲区或者临界区的数目;HANDLE h_SemaphoreMAX_THREAD_NUM; /生/ 产者允许消费者开始消费的信号量;/ 生产消费及辅助函数的声明void Produce(void *p);void Consume(void *p);bool IfInOtherRequest(int);int Fin

9、dProducePositon();int FindBufferPosition(int);int main(void)/ 声明所需变量;DWORD wait_for_all;ifstream inFile;/ 初始化缓冲区;for(int i=0;i MAX_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

10、 = 0;/ 初始化临界区;for(i =0;i n_Buffer_or_Critical;inFile.get();printf( 输入文件是 :n);/ 回显获得的缓冲区的数目信息;printf(%d n,(int) n_Buffer_or_Critical);/ 提取每个线程的信息到相应数据结构中; while(inFile)inFile Thread_Infon_Thread.serial;inFile Thread_Infon_Thread.entity;inFile Thread_Infon_Thread.delay;char c;inFile.get(c);while(c!=n&

11、 !inFile.eof()inFile Thread_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;double Temp_delay = Thread_Infoj.delay;printf( n thread%2d %c %f

12、,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;printf(nn);/ 创建在模拟过程中几个必要的信号量 empty_semaphore=CreateSemaphore(NULL,n_Buffer_or_Critical,n_Buffer_or_Critical,semaphore_for_empty);h_mutex =

13、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

14、) n_Thread;i+)if(Thread_Infoi.entity =P)h_Threadi= CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Produce),&(Thread_Infoi),0,NULL);else h_Threadi=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consume),&(Thread_Infoi),0,NULL);/ 主程序等待各个线程的动作结束;wait_for_all = WaitForMultipleObjects(n_Thread,h_Thread,TRUE,

15、-1); printf( n n 全部生产者和消费者都已完成它们的工作. 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 FindProducePosit

16、ion()int EmptyPosition;for (int i =0;in_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 =0 ;iserial;m_delay = (DWORD)(ThreadInfo*)(p

17、)-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 = FindProducePositio

18、n();ReleaseMutex(h_mutex);/ 生产者在获得自己的空位置并做上标记后,以下的写操作在生产者之间可以并发;/ 核心生产步骤中,程序将生产者的 ID 作为产品编号放入,方便消费者识别 ;printf( 生产者 %2d 开始在缓冲区 %2d 生产产品 .n,m_serial,ProducePos);Buffer_CriticalProducePos = m_serial;printf( 生产者 %2d 完成生产过程 :n ,m_serial);printf(缓冲区 %2d :%3d n ,ProducePos,Buffer_CriticalProducePos);/ 使生产者

19、写的缓冲区可以被多个消费者使用,实现读写同步;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_Critical

温馨提示

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

评论

0/150

提交评论