线程技术的文档_第1页
线程技术的文档_第2页
线程技术的文档_第3页
线程技术的文档_第4页
线程技术的文档_第5页
已阅读5页,还剩41页未读 继续免费阅读

下载本文档

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

文档简介

MultithreadedProgrammingWiththeWin32APIAndrewTuckerDebuggerDevelopmentLeadMarch13,1998WhatWeWillCover

IntrotoMultithreadedConceptsStartingandStoppingThreadsSynchronizationDebuggingandTestingIssuesInterprocessCommunicationAdvancedTopicsandAdditionalResourcesCaveatsMultithreadedfeaturesetsdifferbetweenNT,Win95andCEandversionsofthesameOSIntrotoMultithreadedConceptsWhatisathread?“pathofexecutioninaprocess”ownedbyasingleprocessallprocesseshavemainthread,somehavemorehasfullaccesstoprocessaddressspaceProcess1Process2ProcessNMainT1T2T3MainMainT1OperatingSystemIntrotoMultithreadedConceptsScheduling-cooperativevspreemptivePreemptive-allowathreadtoexecuteforaspecifiedamountoftimeandthenautomaticallyperformsa“contextswitch”tochangetoanewthread(e.G.NT,win95,WCE)Cooperative-performscontextswitchonlywhentheuserspecifies(“manuallyscheduled”)Win16isneither:multitasking,butnotmultithreadStartingandStoppingThreadsCreateThreadAPIHANDLECreateThread(LPSECURITY_ATTRIBUTESlpsa, //pointertothreadsecurityattributes DWORDdwStackSize, //initialthreadstacksize,inbytes LPTHREAD_START_ROUTINElpStartAddress, //pointertothreadfunction LPVOIDlpParameter, //argumentfornewthread DWORDdwCreationFlags, //creationflags LPDWORDlpThreadId //pointertoreturnedthreadidentifier );_beginthreadexCRTfunctionunsignedlong_beginthreadex(void*security, unsignedstack_size, unsigned(__stdcall*start_address)(void*), void*arglist, unsignedinitflag, unsigned*thrdaddr);So,what’sthedifference?StartingandStoppingThreadsDifferenceistheinitializationoftheCRTlibraryLinkingwithmultithreadedCRTisnotenoughDWORDThreadFunc(PVOIDpv){char*psz=strtok((char*)pv,“;”);while(psz){….processdata….psz=strtok(NULL.“;”);}}intmain(){//BUG-use_beginthreadextoensurethreadsafeCRTHANDLEhthrd1=CreateThread(…ThreadFunc…);HANDLEhthrd2=CreateThread(…ThreadFunc…);}_beginthreadexcreatesastructuretoensureglobalandstaticCRTvariablesarethread-specificStartingandStoppingThreadsThreadfunctionshavethefollowingprototype:

DWORDWINAPIThreadFunc(PVOIDpv);Itisveryusefultousepvasapointertoauser-definedstructuretopassextradataStartingandStoppingThreadsAreturnwillautomaticallycalltherespective_endthreadexorEndThreadAPIAreturndoesnotclosethehandlefromthecreationroutine(usermustcallCloseHandletoavoidresourceleak)Threadsshouldbeself-terminating(avoidtheTerminateThreadAPI)StartingandStoppingThreadsReasonstoavoidtheTerminateThreadAPI:Ifthetargetthreadownsacriticalsection,itwillnotbereleasedIfthetargetthreadisexecutingcertainkernelcalls,thekernelstateforthethread’sprocesscouldbeinconsistentIfthetargetthreadismanipulatingtheglobalstateofasharedDLL,thestateoftheDLLcouldbedestroyed,affectingotherusersoftheDLLStartingandStoppingThreadsUsingaC++memberasathreadfunction(fixingthe‘this’problem):classThreadedClass{public:ThreadedClass();BOOLStart();voidStop();private:HANDLEm_hThread;BOOLm_bRunning;staticUINTWINAPIStaticThreadFunc(LPVOIDlpv);DWORDMemberThreadFunc();};UINTWINAPIThreadedClass::StaticThreadFunc( LPVOIDlpv){ThreadedClass*pThis=(ThreadedClass*)lpv;returnpThis->MemberThreadFunc();}DWORDThreadedClass::MemberThreadFunc(){while(m_bRunning){…doprocessing... }}BOOLThreadedClass::Start(DWORDdwStart){UINTnTID;m_hThread=(HANDLE)_beginthreadex(NULL,0, StaticThreadFunc,this,0,&nTID)returnTRUE;}voidThreadedClass::Stop(){m_bRunning=FALSE;//waitforthreadtofinishDWORDdwExitCode;GetExitCodeThread(m_hThread,&dwExitCode);while(dwExitCode==STILL_ACTIVE){GetExitCodeThread(m_hThread,&dwExitCode);}m_hThread=0;}intmain(){

ThreadedClasstc1,tc2;tc1.Start(5);tc2.Start(5000);Sleep(3000);tc1.Stop();tc2.Stop();return0;}StartingandStoppingThreadsSuspendThreadandResumeThreadallowyoutopauseandrestartanythreadSuspensionstateisacountnotaboolean-callsshouldbebalancedExample:hittingabpinadebuggercausesallcurrentthreadstobesuspendedandresumedonsteporgoStartingandStoppingThreadsGetCurrentThreadandGetCurrentThreadIdareusefulforidentifyingcurrentthreadGetExitCodeThreadisusefulfordeterminingifathreadisstillaliveGetThreadTimesisusefulforperformanceanalysisandmeasurementSynchronizationUsedtocoordinatetheactivitiesofconcurrentlyrunningthreadsAlwaysavoidcoordinatingwithapollloopwhenpossibleforefficiencyreasonsSynchronizationInterlockedfunctionsCriticalSectionsWaitfunctionsMutexesSemaphoresEventsWaitableTimersSynchronizationInterlockedfunctions:PVOIDInterlockedCompareExchange(PVOID*destination,PVOIDExchange,PVOIDComperand) if(*Destination==Comperand) *Destination=Exchange;LONGInterlockedExchange(LPLONGTarget,LONGValue) *Target=Value;LONGInterlockedExchangeAdd(LPLONGAddend,LONGIncrement) *Addend+=Increment;LONGInterlockedDecrement(LPLONGAddend) *Addend-=1;LONGInterlockedIncrement(LPLONGAddend) *Addend+=1;Alloperationsareguaranteedtobe“atomic”-theentireroutinewillexecutew/oacontextswitchSynchronizationWhymustsimpleoperationslikeincrementinganintegerbe“atomic”?MultipleCPUinstructionsarerequiredfortheactualimplementation.Ifweretrievedavariableandwerethenpreemptedbyathreadthatchangedthatvariable,wewouldbeusingthewrongvalue.SynchronizationAcriticalsectionisatoolforguaranteeingthatonlyonethreadisexecutingasectionofcodeatanytimevoidInitializeCriticalSection(LPCRITICAL_SECTIONlpCritSec)voidDeleteCriticalSection(LPCRITICAL_SECTIONlpCritSec)voidEnterCriticalSection(LPCRITICAL_SECTIONlpCritSec)voidLeaveCriticalSection(LPCRITICAL_SECTIONlpCritSec)BOOLTryEnterCriticalSection(LPCRITICAL_SECTIONlpCritSec)Synchronization EnterCriticalSectionwillnotblockonnestedcallsaslongasthecallsareinthesamethread.CallstoLeaveCriticalSectionmuststillbebalancedSynchronization Criticalsectionexample:countingsourcelinesinmultiplefilesDWORDg_dwTotalLineCount=0;DWORDCountLinesThread(PVOIDpv){PSTRpszFileName=(PSTR)pv;DWORDdwCount;dwCount=CountSourceLines(pszFileName);EnterCriticalSection(&cs);g_dwTotalLineCount+=dwCount;LeaveCriticalSection(&cs);return0;}voidUpdateSourceLineCount(){FileNameListfnl;HANDLE*pHandleList;CRITICAL_SECTIONcs;GetFileNameList(&fnl);InitializeCriticalSection(&cs);pHandleList=malloc(sizeof(HANDLE)*fnl.Size());for(inti=0;i<FileNameList.Size();i++)pHandleList[i]=_beginthreadex(…CountLinesThread,fnl[i]…);//we’llcoverthisshortly…WaitForMultipleObjects(fnl.Size(),pHandleList,TRUE,INFINITE);DeleteCriticalSection(&cs);…processg_dwTotalLineCount...}SynchronizationWaitfunctions-allowyoutopauseuntiloneormoreobjectsbecomesignaledAtalltimes,anobjectisinoneoftwostates:signaledornonsignaledPicturesignaledasaflagbeingraisedandnonsignaledasaflagbeinglowered-thewaitfunctionsarewatchingforaflagtoberaisedSynchronizationTypesofobjectsthatcanbe“waitedon“:ProcessesThreadsConsoleInputFileChangeNotificationsMutexes*Semaphores*Events*WaitableTimers*SynchronizationProcessesandthreadsarenon-signaledatcreationandbecomesignaledwhentheyterminateSynchronizationDWORDWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds)ReturnsWAIT_OBJECT_0ifhHandlehasbecomesignaledorWAIT_TIMEOUTifdwMillisecondselapsedandtheobjectisstillnon-signaledDWORDWaitForMultipleObjects(DWORDnCount,HANDLE*pHandles,BOOLbWaitAll,DWORDdwMilliseconds)IfbWaitAllisFALSEandoneoftheobjecthandleswassignaled,thereturnvalueminusWAIT_OBJECT_0isthearrayindexofthathandle.IfbWaitAllisTRUEandalloftheobjectsbecomesignaledthereturnvalueminusWAIT_OBJECT_0isavalidindexintothehandlearray.IfdwMillisecondselapsedandnoobjectwassignaled,WAIT_TIMEOUTisreturned.nCountcanbenomorethanMAXIMUM_WAIT_OBJECTS(currentlydefinedas64)INFINITEcanbeusedasatimeoutvalueSynchronizationMutexesprovidemutuallyexclusiveaccesstoanobject(hencethename)HANDLECreateMutex(LPSECURITY)ATTRIBUTESlpsa,BOOLbInitialOwner,LPCTSTRlpName)Ownershipisequivalenttothenonsignaledstate-ifbInitialOwnerisTRUEthecreationstateofthemutexisnonsignaledlpNameisoptionalReleaseMutexisusedtoendownershipSynchronizationWhat’sthedifferencebetweenacriticalsectionandamutex?AmutexisaOSkernelobject,andcanthusbeusedacrossprocessboundaries.AcriticalsectionislimitedtotheprocessinwhichitwascreatedSynchronizationTwomethodstogetahandletoanamedmutexcreatedbyanotherprocess:OpenMutex-returnshandletoanexistingmutexCreateMutex-createsorreturnshandletoanexistingmutex.GetLastErrorwillreturnERROR_ALREADY_EXISTSforthelattercaseSynchronizationComparingmutexandcriticalsectionperformanceSynchronizationAmutexwillnotblockonnestedcallsaslongastheyareinthesamethread.ReleaseMutexcallsmuststillbebalancedExamplesofwhentouseamutex:ErrorloggingsystemthatcanbeusedfromanyprocessDetectingmultipleinstancesofanapplicationSynchronizationSemaphoresallowaccesstoaresourcetobelimitedtoafixednumberHANDLECreateSemaphore(LPSECURITY_ATTRIBUTElpsa,LONGcSemInitial,LONGcSemMax,LPCTSTRlpName)SemaphoresareinthesignaledstatewhentheiravailablecountisgreaterthanzeroReleaseSemaphoreisusedtodecrementusageConceptually,amutexisabinarysemaphoreSynchronizationNamedsemaphorescanbeusedacrossprocessboundarieswithOpenSemaphoreandCreateSemaphoreCanbeusedtosolvetheclassic“singlewriter/multiplereaders”problemSynchronizationExample:limitingnumberofentriesinaqueueconstintQUEUE_SIZE=5;HANDLEg_hSem=NULL;longg_iCurSize=0;UINTWINAPIPrintJob(PVOIDpv){WaitForSingleObject(g_hSem,INFINITE);InterlockedIncrement(&g_iCurSize);printf("%08lX-enteredqueue:size=%d\n",GetCurrentThreadId(),g_iCurSize);Sleep(500);//printjob....InterlockedDecrement(&g_iCurSize);longlPrev;ReleaseSemaphore(g_hSem,1,&lPrev);return0;}intmain(){constintMAX_THREADS=64;HANDLEhThreads[MAX_THREADS];g_hSem=CreateSemaphore(NULL,QUEUE_SIZE,QUEUE_SIZE,NULL);UINTdwTID;for(inti=0;i<MAX_THREADS;i++)hThreads[i]=(HANDLE)_beginthreadex(NULL,0,PrintJob,NULL,0,&dwTID);WaitForMultipleObjects(MAX_THREADS,hThreads,TRUE,INFINITE);return0;}Synchronization EventsprovidenotificationwhensomeconditionhasbeenmetHANDLECreateEvent(LPSECURITY_ATTRIBUTESlpsa,BOOLbManualReset,BOOLbInitialState,LPCTSTRlpName)IfbInitialStateisTRUE,objectiscreatedinthesignaledstatebManualResetspecifiesthetypeofeventrequestedSynchronizationTwokindsofeventobjects:Autoreset-whensignaleditisautomaticallychangedtoanonsignaledstateafterasinglewaitingthreadhasbeenreleasedManualreset-whensignaleditremainsinthesignaledstateuntilitismanuallychangedtothenonsignaledstateSynchronizationNamedeventobjectscanbeusedacrossprocessboundarieswithOpenEventandCreateEventSetEventsetstheobjectstatetosignaledResetEventsetstheobjectstatetononsignaledPulseEventconceptuallycallsSetEvent/ResetEventsequentially,but...Synchronization PulseEventvsSetEventSynchronizationExample:displayingOutputDebugStringtextwithoutadebuggerintmain(){HANDLEhAckEvent,hReadyEvent;PSTRpszBuffer;hAckEvent=CreateEvent(NULL,FALSE,FALSE,“DBWIN_BUFFER_READY”);if(GetLastError()==ERROR_ALREADY_EXISTS){//handlemultipleinstancecase}hReadyEvent=CreateEvent(NULL,FALSE,FALSE,“DBWIN_DATA_READY”);pszBuffer=/*getpointertodatainmemorymappedfile*/;

SetEvent(hAckEvent);while(TRUE){intret=WaitForSingleObject(hReadyEvent,INFINITE);if(ret!=WAIT_OBJECT_0){//handleerror}else{printf(pszBuffer);SetEvent(hAckEvent);}}}SynchronizationWaitabletimersarekernelobjectsthatprovideasignalataspecifiedtimeintervalHANDLECreateWaitableTimer(LPSECURITY_ATTRIBUTESlpsa,BOOLbManualReset,LPCTSTRlpName)Manual/autoresetbehaviorisidenticaltoeventsTimeintervalisspecifiedwithSetWaitableTimerSynchronizationBOOLSetWaitableTimer(HANDLEhTimer,LARGE_INTEGER*pDueTime,LONGlPeriod,PTIMERACPROUTINEpfnCompletion,PVOIDpArg,BOOLfResume)pDueTimespecifieswhenthetimershouldgooffforthefirsttime(positiveisabsolute,negativeisrelative)lPeriodspecifieshowfrequentlytogooffaftertheinitialtimefResumecontrolswhetherthesystemisawakenedwhentimerissignaledSynchronizationConsecutivecallstoSetWaitableTimeroverwriteeachotherCancelWaitabletimerstopsthetimersothatitwillnotgooffagain(unlessSetWaitableTimeriscalled)SynchronizationExample:firinganeventeveryNsecondsconstintMAX_TIMES=3;constintN=10;DWORDWINAPIThreadFunc(PVOIDpv){HANDLEhTimer=(HANDLE)pv;intiCount=0;DWORDdwErr=0;while(TRUE){if(WaitForSingleObject(hTimer,INFINITE)==WAIT_OBJECT_0){…handletimerevent...if(++iCount>=MAX_TIMES)break;

温馨提示

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

评论

0/150

提交评论