资源描述:
《线程的同步和互斥问题》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
实验二线程的同步和互斥问题一.实验内容:编写程序实现并发线程之间的同步和互斥问题。线程间的互斥:并发执行的线程共享某些类临界资源,对临界资源的访问应当采取互斥的机制。线程间的同步:并发执行的线程间通常存在相互制约的关系,线程必须遵循一定的规则来执行,同步机制可以协调相互制约的关系。二.实验目的和要求1)了解进程同步与互斥的概念,掌握编写进程同步、互斥的实例。2)解决一类典型的进程间同步问题,如生产者-消费者问题,读者-写者问题等。三.实验方法和步骤1.实验方法掌握同步与互斥的机制,选取合适的问题,给出演示程序的设计思想,包括流程图的形式;选取C、C++、VC、JAVA等计算机语言,编程调试,最终给出运行正确的程序。2.程序设计(1)线程间互斥:分析问题,创建多个线程,找出临界资源,划出正确的临界区,根据互斥机制的操作模式,编写程序。互斥机制的操作模式:p(mutex);/*关锁*/临界区的操作;v(mutex);/*开锁*/(2)线程间同步——读者-写者问题示例:在Windows2000环境下,创建一个包含n个线程的控制台进程。用这n个线程来表示n个读者或写者。每个线程按相应测试数据文件的要求,进行读写操作。请用信号量机制分别实现读者优先和写者优先的读者-写者问题。读者-写者问题的读写操作限制: 1)写-写互斥; 2)读-写互斥; 3)读-读允许;运行结果显示要求:要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确信所有处理都遵守相应的读写操作限制。测试数据文件格式测试数据文件包括n行测试数据,分别描述创建的n个线程是读者还是写者,以及读写操作的开始时间和持续时间。每行测试数据包括四个字段,各字段间用空格分隔。第一字段为一个正整数,表示线程序号。第二字段表示相应线程角色,R表示读者是,W表示写者。第三字段为一个正数,表示读写操作的开始时间。线程创建后,延时相应时间(单位为秒)后发出对共享资源的读写申请。第四字段为一个正数,表示读写操作的持续时间。当线程读写申请成功后,开始对共享资源的读写操作,该操作持续相应时间后结束,并释放共享资源。 下面是一个测试数据文件的例子: 1R35 2W45 3R52 4R65 5W5.13 与实验相关的API介绍 在本实验中可能涉及的API有: 线程控制: CreateThread完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函 数;它的返回值为所创建线程的句柄。 HANDLECreateThread( LPSECURITY_ATTRIBUTESlpThreadAttributes,//SD DWORDdwStackSize,//initialstacksize LPTHREAD_START_ROUTINElpStartAddress,//thread function LPVOIDlpParameter,//threadargument DWORDdwCreationFlags,//creationoption LPDWORDlpThreadId//threadidentifier ); ExitThread用于结束当前线程。 VOIDExitThread( DWORDdwExitCode//exitcodeforthisthread ); Sleep可在指定的时间内挂起当前线程。 VOIDSleep( DWORDdwMilliseconds//sleeptime ); 信号量控制: CreateMutex创建一个互斥对象,返回对象句柄; HANDLECreateMutex( LPSECURITY_ATTRIBUTESlpMutexAttributes,//SD BOOLbInitialOwner,//initialowner LPCTSTRlpName//objectname ); OpenMutex打开并返回一个已存在的互斥对象句柄,用于后续访问; HANDLEOpenMutex( DWORDdwDesiredAccess,//access BOOLbInheritHandle,//inheritanceoption LPCTSTRlpName//objectname ); ReleaseMutex释放对互斥对象的占用,使之成为可用。 BOOLReleaseMutex( HANDLEhMutex//handletomutex ); WaitForSingleObject可在指定的时间内等待指定对象为可用状态; DWORDWaitForSingleObject( HANDLEhHandle,//handletoobject DWORDdwMilliseconds//time-outinterval ); 实验程序代码 #include #include #include #include #include #include #defineMAX_PERSON100 #defineREADER0 #defineWRITER1 #defineEND-1 #defineRREADER #defineWWRITER typedefstruct_Person { HANDLEm_hThread; intm_nType; intm_nStartTime; intm_nWorkTime; intm_nID; }Person; Persong_Persons[MAX_PERSON]; intg_NumPerson=0; longg_CurrentTime=0; intg_PersonLists[]={ 1,R,5,5, 2,W,4,5, 3,R,2,2, 4,R,1,5, END, }; intg_NumOfReading=0; HANDLEg_hReadMutex; HANDLEg_hWriteMutex; voidCheckPersonList(int*pPersonList); boolCreateReader(intStartTime,intWorkTime); boolCreateWriter(intStartTime,intWorkTime); DWORDWINAPIReaderProc(LPVOIDlpParam); DWORDWINAPIWriterProc(LPVOIDlpParam); intmain() { g_hReadMutex=CreateMutex(NULL,FALSE,NULL); g_hWriteMutex=CreateMutex(NULL,FALSE,NULL); g_CurrentTime=0; while(true) { CheckPersonList(g_PersonLists); g_CurrentTime++; Sleep(300); printf("CurrentTime=%d ",g_CurrentTime); } return0; } voidCheckPersonList(int*pPersonLists) { inti=0; int*pList=pPersonLists; boolRet; while(pList[0]!=END) { if(pList[2]==g_CurrentTime) { switch(pList[1]) { caseR: Ret=CreateReader(pList[2],pList[3]); break; caseW: Ret=CreateWriter(pList[2],pList[3]); break; } if(!Ret) printf("CreatePerson%diswrong ",pList[0]); } pList+=4;//movetonextpersonlist } } DWORDWINAPIReaderProc(LPVOIDlpParam) { Person*pPerson=(Person*)lpParam; printf("Reader%disrequesttheSharedBuffer... ",pPerson->m_nID); WaitForSingleObject(g_hReadMutex,INFINITE); if(g_NumOfReading==0) { WaitForSingleObject(g_hWriteMutex,INFINITE); } g_NumOfReading++; ReleaseMutex(g_hReadMutex); printf("Reader%disrequestok ",pPerson->m_nID); //modifythereader'srealstarttime pPerson->m_nStartTime=g_CurrentTime; printf("Reader%disReadingtheSharedBuffer... ",pPerson->m_nID); while(g_CurrentTime<=pPerson->m_nStartTime+pPerson->m_nWorkTime) { //..performreadoperations } printf("Reader%disExit... ",pPerson->m_nID); WaitForSingleObject(g_hReadMutex,INFINITE); g_NumOfReading--; if(g_NumOfReading==0) ReleaseMutex(g_hWriteMutex); ReleaseMutex(g_hReadMutex); ExitThread(0); return0; } DWORDWINAPIWriterProc(LPVOIDlpParam) { WaitForSingleObject(g_hWriteMutex,INFINITE); Person*pPerson=(Person*)lpParam; //modifythewriter'srealstarttime pPerson->m_nStartTime=g_CurrentTime; printf("Writer%disWrittingtheSharedBuffer... ",pPerson->m_nID); while(g_CurrentTime<=pPerson->m_nStartTime+pPerson->m_nWorkTime) { //..performwriteoperations } printf("Writer%disExit... ",pPerson->m_nID); ReleaseMutex(g_hWriteMutex); ExitThread(0); return0; } boolCreateReader(intStartTime,intWorkTime) { DWORDdwThreadID; if(g_NumPerson>=MAX_PERSON) returnfalse; Person*pPerson=&g_Persons[g_NumPerson]; pPerson->m_nID=g_NumPerson; pPerson->m_nStartTime=StartTime; pPerson->m_nWorkTime=WorkTime; pPerson->m_nType=READER; g_NumPerson++; //CreateanNewThread pPerson->m_hThread=CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID); if(pPerson->m_hThread==NULL) returnfalse; returntrue; } boolCreateWriter(intStartTime,intWorkTime) { DWORDdwThreadID; if(g_NumPerson>=MAX_PERSON) returnfalse; Person*pPerson=&g_Persons[g_NumPerson]; pPerson->m_nID=g_NumPerson; pPerson->m_nStartTime=StartTime; pPerson->m_nWorkTime=WorkTime; pPerson->m_nType=WRITER; g_NumPerson++; //CreateanNewThread pPerson->m_hThread=CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID); if(pPerson->m_hThread==NULL) returnfalse; returntrue; }一.实验结果分析通过运行多线程并发执行,观察运行的效果,分析互斥与同步的运行效果。在互斥机制下,能否同时访问临界资源;在同步机制下,线程的执行是否存在固定的协调次序,如何修改程序来控制线程的协调运行?