您好,欢迎访问三七文档
实验二(2)进程同步一、实验目的1、生产者-消费者问题是很经典很具有代表性的进程同步问题,计算机中的很多同步问题都可抽象为生产者-消费者问题,通过本实验的练习,希望能加深学生对进程同步问题的认识与理解。2、熟悉VC的使用,培养和提高学生的分析问题、解决问题的能力。二、实验内容及其要求1.实验内容以生产者/消费者模型为依据,创建一个控制台进程,在该进程中创建n个线程模拟生产者和消费者,实现进程(线程)的同步与互斥。2.实验要求学习并理解生产者/消费者模型及其同步/互斥规则;设计程序,实现生产者/消费者进程(线程)的同步与互斥;三、实验算法分析1、实验程序的结构图(流程图);2、数据结构及信号量定义的说明;(1)CreateThread功能——创建一个在调用进程的地址空间中执行的线程格式HANDLECreateThread(LPSECURITY_ATTRIBUTESlpThreadAttributes,DWORDdwStackSize,开始ProduceWaitBufferWaitProductsConsume结束WhileproduceWhileconsumeLPTHREAD_START_ROUTINElpStartAddress,LPVOIDlpParamiter,DWORDdwCreationFlags,LpdwordlpThread);参数说明lpThreadAttributes——指向一个LPSECURITY_ATTRIBUTES(新线程的安全性描述符)。dwStackSize——定义原始堆栈大小。lpStartAddress——指向使用LPTHRAED_START_ROUTINE类型定义的函数。lpParamiter——定义一个给进程传递参数的指针。dwCreationFlags——定义控制线程创建的附加标志。lpThread——保存线程标志符(32位)(2)CreateMutex功能——创建一个命名或匿名的互斥量对象格式HANDLECreateMutex(LPSECURITY_ATTRIBUTESlpMutexAttributes,BOOLbInitialOwner,LPCTSTRlpName);bInitialOwner——指示当前线程是否马上拥有该互斥量(即马参数说明lpMutexAttributes——必须取值NULL。上加锁)。lpName——互斥量名称。(3)CreateSemaphore功能——创建一个命名或匿名的信号量对象格式HANDLECreateSemaphore(LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,LONGlInitialCount,LONGlMaximumCount,LPCTSTRlpName);参数说明lpSemaphoreAttributes——必须取值NULL。lInitialCount——信号量的初始值。该值大于0,但小于lMaximumCount指定的最大值。lMaximumCount——信号量的最大值。lpName——信号量名称。(4)WaitForSingleObject功能——使程序处于等待状态,直到信号量hHandle出现(即其值大于等于1)或超过规定的等待时间格式DWORDWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds);参数说明hHandle——信号量指针。dwMilliseconds——等待的最长时间(INFINITE为无限等待)。(5)ReleaseSemaphore功能——对指定信号量加上一个指定大小的量。成功执行则返回非0值格式BOOLReleaseSemaphore(HANDLEhSemaphore,LONGlReleaseCount,LPLONGlppreviousCount);参数说明hSemaphore——信号量指针。lReleaseCount——信号量的增量。lppreviousCount——保存信号量当前值。(6)ReleaseMutex功能——打开互斥锁,即把互斥量加1。成功调用则返回0格式BOOLReleaseMutex(HANDLEhMutex);参数说明hMutex——互斥量指针。(7)InitializeCriticalSection功能——初始化临界区对象格式VOIDInitializeCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);参数说明lpCriticalSection——指向临界区对象的指针。(8)EnterCriticalSection功能——等待指定临界区对象的所有权格式VOIDenterCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);参数说明lpCriticalSection——指向临界区对象的指针。(9)LeaveCriticalSection功能——释放指定临界区对象的所有权格式VOIDLeaveCriticalSection(LPCRITICAL_SECTIONlpCriticalSection);参数说明lpCriticalSection——指向临界区对象的指针4、主要算法创建生产者和消费者线程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);elseh_Thread[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(Consume),&(Thread_Info[i]),0,NULL);}生产者进程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(Producer%2dsendstheproducerequire.\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(Producer%2dbegintoproduceatposition%2d.\n,m_serial,ProducePos);Buffer_Critical[ProducePos]=m_serial;printf(Producer%2dfinishproducing:\n,m_serial);printf(position[%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;im_requestNum;i++)m_thread_request[i]=((ThreadInfo*)(p))-thread_request[i];Sleep(m_delay);//循环进行所需产品的消费for(i=0;im_requestNum;i++){//请求消费下一个产品printf(Consumer%2drequesttoconsume%2dproduct\n,m_serial,m_thread_request[i]);//如果对应生产者没有生产,则等待;如果生产了,允许的消费者数目-1;实现了读写同步;wait_for_semaphore=WaitForSingleObject(h_Semaphore[m_thread_request[i]],-1);//查询所需产品放到缓冲区的号intBufferPos=FindBufferPosition(m_thread_request[i]);//开始进行具体缓冲区的消费处理,读和读在该缓冲区上仍然是互斥的;//进入临界区后执行消费动作;并在完成此次请求后,通知另外的消费者本处请求已//经满足;同时如果对应的产品使用完毕,就做相应处理;并给出相应动作的界面提//示;该相应处理指将相应缓冲区清空,并增加代表空缓冲区的信号量;EnterCriticalSection(&PC_Critical[BufferPos]);printf(Consumer%2dbegintoconsume%2dproduct\n,m_serial,m_thread_request[i]);((ThreadInfo*)(p))-thread_request[i]=-1;if(!IfInOtherRequest(m_thread_request[i])){Buffer_Critical[BufferPos]=-1;//标记缓冲区为空;printf(Consumer%2dfinishconsuming%2d:\n,m_serial,m_thread_request[i]);printf(position[%2d]:%3d\n,BufferPos,Buffer_Critical[BufferPos]);ReleaseSemaphore(empty_semaphore,1,NULL);}else{printf(Consumer%2dfinishconsumingproduct%2d\n,m_serial,m_thread_request[i]);}//离开临界区LeaveCriticalSection(&PC_Critical[BufferPos]);}}示例程序源代码:#includewindows.h#includefstream.h#includestdio.h#includestring#includeconio.h//定义常量;//此程序允许的最大临界区数;#defineMAX_BUFFER_NUM10//秒到微秒的乘法因子;#defineINTE_PER_SEC1000//本程序允许的生产和消费线程的总数;#defineMAX_THREAD_NU
本文标题:实验二进程同步
链接地址:https://www.777doc.com/doc-2458907 .html