化工大學Windows多線程編程_第1頁
化工大學Windows多線程編程_第2頁
化工大學Windows多線程編程_第3頁
化工大學Windows多線程編程_第4頁
化工大學Windows多線程編程_第5頁
已閱讀5頁,還剩67頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第二章Windows多線程編程內容Windows操作系統的一些基本知識Win32API線程庫線程間通信1、Windows操作系統的一些基本知識API內核對象及句柄API(ApplicationProgrammingInterface)API操作系統留給應用程序的一個調用接口,應用程序通過調用操作系統的API而使操作系統去執行應用程序的命令(動作)。WindowsAPI是一套用來控制Windows的各個部件的外觀和行為的預先定義的Windows函數。Win32API即為Microsoft32位平臺的應用程序編程接口。Win32平臺上運行的應用程序都可以調用這些函數。32與64位API函數聲明上沒有明顯區別,但64位編程是需要下載相應的平臺SDK

API(ApplicationProgrammingInterface)直接用win32API編寫的應用程序,程序的執行代碼小,運行效率高MFC用類庫的方式將win32API進行封裝,以類的方式提供給開發者Framework類庫提供了所有應用程序模型都要使用的一個面向對象的API集合內核對象及句柄當應用程序要與系統設備進行交互的時候,將使用到內核對象。出于安全的考慮,進程是不能直接訪問內核對象的,操作系統提供了對應的函數來對它們進行訪問。內核對象是由操作系統內核分配,只能由內核訪問的數據結構,用來管理各種系統資源。內核對象包括:存取符號對象、事件對象、文件對象、作業對象、互斥對象、管道對象、等待計時器對象等都是內核對象。編程時經常要創建、打開和操作它們。內核對象及句柄內核對象由內核擁有,各個進程可以共享內核對象。進程中止執行,它使用的內核對象并不一定會被撤銷。每個內核對象都有一個計數器來存儲有多少個進程在使用它的信息。進程調用時,計數器增1,調用結束,計數器減1。內核對象計數器為零時,銷毀此內核對象。

內核對象及句柄內核對象有安全描述符的保護,安全描述符描述了誰創建了該對象以及誰能夠使用該對象。用于創建內核對象的函數幾乎都有一個指向SECURITY_ATTRIBUTES

結構的指針作為其參數。

大多數應用程序通過傳NULL值,創建具有默認安全性的對象。如果想限制別人對對象的訪問,就需要單獨創建一個SECURITY_ATTRIBUTES對象并對其初始化。內核對象及句柄句柄:創建內核對象時,函數的返回值,標記該內核對象。句柄表:進程被初始化時,系統給進程分配一個句柄表,用于保存該進程使用的內核對象的信息,而句柄值則是相應內核對象在句柄表中的索引值,因此句柄值是進程相關的。內核對象及句柄內核對象創建當利用creat*函數來創建內核對象時,調用該函數的時候內核就為該對象分配一個內存塊,并進行初始化,然后內核再掃描該進程的句柄表,初始化一條記錄并放在句柄表中。關閉內核對象無論進程怎樣創建內核對象,在不使用該對象的時候都應當通過Bool

CloseHandle(HANDLE

hobj)來向操作統聲明結束對該對象的訪問。Win32API線程庫創建線程程的基本本問題創建線程程的API函數操作線程程的API一個簡單單的Windows多線程程程序1創建線程程的基本本問題線程可以以由進程程中的任任意線程程創建,,而進程程的主線線程在進進程加載載時自動動創建。。每個線程程都有自自己的進進入點函函數。主線程的的進入點點函數進入點應用程序類型WinMain需要ANSI字符和字符串的GUI應用程序wWinMain需要Unicode字符和字符串的GUI應用程序Main需要ANSI字符和字符串的CUI應用程序Wmain需要Unicode字符和字符串的CUI應用程序線程函數數的返回回值是該該線程的的退出代代碼線程函數數應盡可可能使用用函數參參數和局局部變量量線程函數數----線程的入入口點DWORDWINAPIThreadFunc(PVOIDpvParam){DWORDdwResult=0;……return(dwResult);}2創建線程程的API函數創建線程程:系統統創建一一個線程程內核對對象。線程內核核對象不不是線程程本身,,而是操操作系統統用來管管理線程程的較小小的數據據結構在進程的的地址空空間分配配內存,,供線程程的堆棧棧使用HANDLECreateThread(PSECURITY_ATTRIBUTESpsa,DWORDcbStack,PTHREAD_START_ROUTINEpStartAddr,PVOIDpvParam,DWORDfdwCreate,PDWORDpdwThreadId);2創建線程程的API函數NULL0函數地址址函數參數數NULL控制創建建線程標標志CREATE_SUSPENDED;0線程ID暫停線程程DWORDSuspendThread(HANDLEhThread)返回值是是線程的的前一個個暫停計計數暫停計數數:是線線程內核核對象的的一個內內部值。。使用要小小心,因因為不知知道暫停停線程運運行時它它在進行行什么操操作。可可能造成成死鎖3操作線程程的API3操作線程程的API恢復線程程DWORDResumeThread(HANDLEhThread);返回值是是線程的的前一個個暫停計計數該函數用用于將處處于暫停停狀態的的線程置置于就緒緒狀態,,使其參參加線程程調度。。3操作線程程的API使線程睡睡眠VOIDSleep(DWORDdwMilliseconds);該函數是是線程暫暫停自己己的運行行,直到到睡眠時時間過去去為止當線程調調用這個個函數時時,它自自動放棄棄剩余的的時間片片,迫使使系統進進行線程程調度。。Windows不是實時時的操作作系統。。3操作線程程的API終止線程程線程函數數返回((最好))通過調用用ExitThread函數,線線程將自自行撤銷銷同一個進進程或另另一個進進程中的的線程調調用TerminateThread函數包含線程程的進程程終止線程返回回函數線程中創創建的C++類對象能能夠正常常撤銷;;操作系統統將正確確地釋放放線程堆堆棧使用用的內存存;系統將線線程的退退出代碼碼設置為為線程函函數的返返回值;;系統將遞遞減線程程內核對對象的使使用計數數。線程調用用這個函函數,強強制線程程終止運運行;操作系統統清除該該線程使使用的所所有系統統資源。。C++類對象將將不被撤撤銷。VOIDExitThread(DWORDdwExitCode);ExitThread函數能夠撤銷銷任何線線程;線程的內內核對象象的使用用計數也也被遞減減;異步運行行的函數數;不撤銷線線程的堆堆棧,直直到進程程終止。。BOOLTerminateThread(HANDLEhThread,DWORDdwExitCode);TerminateThread函數在進程終終止運行行時撤銷銷線程ExitProcess和TerminateProcess函數可以以終止線線程,將將會終止止進程中中的所有有線程;;ExitProcess只能強制制執行本本進程的的退出;;TerminateProcess在一個進進程中強強制結束束其他的的進程;;進程所使使用的資資源被清清除;C++對象撤銷函數數沒有被調用用。VOIDExitProcess(UINTuExitCode);BOOLTerminateProcess(HANDLEhProcess,UINTuExitCode);在進程終止運運行時撤銷線線程4一個簡單的Windows多線程程序((例1)include"windows.h"#include<iostream>usingnamespacestd;DWORDWINAPIThreadFunc(PVOIDpvParam){cout<<"Createdthreadsays'helloWorld!'"<<endl;return0;}intmain(){HANDLEThreadHandle=CreateThread(NULL,0,ThreadFunc,NULL,0,NULL);Sleep(100);cout<<"Mainthreadsays'HelloWorld!"<<endl;getchar();return0;}線程間通信操作系統隨機機調度線程,,程序員不能能預知線程的的執行順序下面兩種情況況下,線程間間需要通信當有多個線程程訪問共享資資源而不希望望共享資源遭遭到破壞;((互斥)當一個線程需需要將某個任任務已經完成成的情況通知知另外一個或或多個線程時時。(同步))Windows線程通信方法法主要有互鎖鎖函數、臨界界段、事件、互斥量量、信號量線程間通信互鎖函數臨界段事件互斥量信號量1、互鎖函數互鎖函數是用用來解決原子子訪問的,主主要針對變量量的原子訪問問;原子訪問:當當線程訪問資資源時,能夠夠確保沒有其其它線程同時時訪問相同的的資源。Longg_x=0;//全局變量DWORDWINAPIThreadFunc1(PVOIDpvParam){g_x++;return0;}DWORDWINAPIThreadFunc2(PVOIDpvParam){g_x++;return0;}MOVEAX,[g_x]INCEAXMOV[g_x],EAX遞增以原子方方式運行1、互鎖函數((例)1、互鎖函數LONGInterlockedExchangeAdd()(PLONGplAddend,LONGlIncrement);Longg_x=0;//全局變量DWORDWINAPIThreadFunc1(PVOIDpvParam){InterlockedExchangeAdd(&g_x,1);return0;}DWORDWINAPIThreadFunc2(PVOIDpvParam){InterlockedExchangeAdd(&g_x,1);return0;}1、互鎖函數以原子操作方方式用第二個個參數的值取取代第一個參參數的當前值值。LONGInterlockedExchange()(PLONGplTarget,LONGlValue);LONGInterlockedExchangePointer()(PVOID*ppvTarget,PVOIDpvValue);1、互鎖函數比較第一個參參數所指的值值和第三個參參數的值,如如果相等,則則將第一個參參數所指的值值置為第二個個參數,如果果不相等則不不進行任何操操作。LONGInterlockedCompareExchange()(PLONGplDestination,LONGlExchange,LONGlComparand);LONGInterlockedCompareExchangePointer()(PVOID*ppvDestination,PVOIDpvExchange,PVOIDpvComparand);2、臨界段互鎖函數:以以原子操作方方式修改單個個值臨界段:以原原子方式修改改復雜的數據據結構。臨界段:關鍵鍵代碼段,是是指一小段代代碼,同一個個時刻,只能能有一個線程程具有訪問權權。多個線程訪問問同一個臨界界區的原則::一次最多只能能一個線程停停留在臨界區區內;不能讓一個線線程無限地停停留在臨界區區內,否則其其它線程將不不能進入該臨臨界區2、臨界段相相關API函數首先定義一個個臨界段對象象(通常全局局變量)CRITICAL_SECTIONcs臨界段對象初初始化InitializeCriticalSection(&cs)進入臨界段EnterCriticalSection(&cs)離開臨界段LeaveCriticalSection(&cs)釋放臨界段對對象DeleteCriticalSection(&cs)臨界段例例#include<windows.h>#include<fstream>fstreamfile;DWORDWINAPIThreadFunc1(PVOIDparam){for(inti=1;i<=1000;i++){file<<"ThreadFunc1Output"<<i<<endl;}return0;}DWORDWINAPIThreadFunc2(PVOIDparam){for(inti=1;i<=1000;i++){file<<"ThreadFunc2Output"<<i<<endl;}return0;}intmain(){file.open("data.txt",ios::out);HANDLEThreadHandle1=CreateThread(NULL,0,ThreadFunc1,NULL,0,NULL);HANDLEThreadHandle2=CreateThread(NULL,0,ThreadFunc2,NULL,0,NULL);HANDLEhThread[2]={ThreadHandle1,ThreadHandle2};WaitForMultipleObjects(2,hThread,TRUE,INFINITE);file.close();return0;}加上臨界段段#include<windows.h>#include<fstream>fstreamfile;CRITICAL_SECTIONcs;DWORDWINAPIThreadFunc1(PVOIDparam){for(inti=1;i<=1000;i++){EnterCriticalSection(&cs);file<<"ThreadFunc1Output"<<i<<endl;LeaveCriticalSection(&cs);}return0;}DWORDWINAPIThreadFunc2(PVOIDparam){for(inti=1;i<=1000;i++){EnterCriticalSection(&cs);file<<"ThreadFunc2Output"<<i<<endl;LeaveCriticalSection(&cs);}return0;}使用內核對對象的線程程間通信互鎖函數和和臨界段都都是在用戶戶態實現線線程通信的的,優點速速度快用戶態機制制只能實現現同一進程程內線程通通信。內核對象機機制可以實實現不同進進程內線程程的通信,,缺點速度度慢。包含通知狀狀態和未通通知狀態內內核屬性的內核對象象有:進程,線程程,作業,文文件,控制制臺輸入文件修改通通知,事件件,可等待待定時器信號量,互互斥量等待函數::使線程進進入等待狀狀態,直到一個對對象變為已已通知狀態態。DWORDWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds);參數dwMilliseconds有兩個特殊殊值:0,則該函數數立即返回回;INFINITE,則線程被被掛起,直直到hHandle所指向的對對象變為已已通知狀態態。使用用內內核核對對象象的的線線程程間間通通信信等待待函函數數::可以以保保證證線線程程的的同同步步。DWORDWaitForMultipleObject(DWORDdwCount,CONSTHANDLE*phHandle,BOOLfWaitAll,DWORDdwMilliseconds);使用用內內核核對對象象的的線線程程間間通通信信3、事事件件事件件內內核核對對象象是是最最簡簡單單的的對對象象。。一個個使使用用計計數數一個個布布爾爾值值,,指指明明該該事事件件是是自自動動重重置置事事件件((false),,還還是是人人工工重重置置事事件件((true);;一個個布布爾爾值值,,指指明明該該事事件件是是已已通通知知狀狀態態,,還還是是未未通通知知狀狀態態。。當人人工工重重置置事事件件得得到到通通知知時時,,等等待待該該事事件件的的所所有有線線程程均均變變為為可可調調度度事事件件;;當自自動動重重置置事事件件得得到到通通知知時時,,等等待待該該事事件件的的線創建建事事件件內內核核對對象象,,返返回回句句柄柄。。HANDLECreateEvent(PSECURITY_ATTRIBUTESpsa,//安全全屬屬性性BOOLfManualReset,//重置置方方式式BOOLfInitialState,//初始始狀狀態態PCTSTRpszName//對象象名名稱稱);3、事事件件其它它進進程程中中的的線線程程可可以以獲獲得得事事件件對對象象的的訪訪問問權權HANDLEOpenEvent(DWORDfdwAccess,BOOLfInherit,PCTSTRpszName);EVENT_ALL_ACCESS3、事件一旦事件件已經創創建,就就可以直直接控制制它的狀狀態將事件設設置為已已通知狀狀態BOOLSetEvent(HANDLEhEvent);將事件設設置為未未通知狀狀態BOOLResetEvent(HANDLEhEvent);3、事件3、事件事件的主主要用途途是標志志事件的的發生,,并以此此協調線線程的執執行順序序。例子:用用戶在主主線程輸輸入命令令,控制制新建線線程的運運行。#include<windows.h>#include<iostream>#include<string>usingnamespacestd;CRITICAL_SECTIONcs;DWORDWINAPIThreadFunc(PVOIDparam){EnterCriticalSection(&cs);cout<<"CreateThread:Createthreadisstarted"<<endl;cout<<"CreateThread:Createthreadiswaitingcontinuecommand.."<<endl;LeaveCriticalSection(&cs);HANDLEphEvent=OpenEvent(EVENT_ALL_ACCESS,TRUE,"ContinueCommand");WaitForSingleObject(phEvent,INFINITE);cout<<"CreateThread:Recievedcontinuecommand."<<endl;cout<<"CreateThread:Threadrunsagain."<<endl;Sleep(2000);cout<<"CreateThread:Threadfinished."<<endl;return0;}intmain(){InitializeCriticalSection(&cs);HANDLEhEvent=CreateEvent(NULL,FALSE,FALSE,"ContinueCommand");cout<<"MainThread:Creatingnewthread."<<endl;HANDLEThreadHandle=CreateThread(NULL,0,ThreadFunc,NULL,CREATE_SUSPENDED,NULL);cout<<"MainThread:Newthreadcreated."<<endl;ResumeThread(ThreadHandle);stringinput;while(TRUE){EnterCriticalSection(&cs);cout<<"MainThread:inputcommand,please"<<endl;LeaveCriticalSection(&cs);cout<<">";cin>>input;if(input=="continue"){cout<<"MainThread:Letthreadcontinuerun"<<endl;SetEvent(hEvent);break;}}WaitForSingleObject(ThreadHandle,INFINITE);cout<<"MainThread:Createthreadfinished"<<endl;DeleteCriticalSection(&cs);CloseHandle(hEvent);return0;}4、互斥量量互斥量是是一個種種內核對對象,確確保線程程擁有對對單個資資源的互互斥訪問問權。一個使用用數量一個線程程ID一個遞歸歸計數器器互斥量的的行為特特征與臨臨界段相相同,互互斥量屬屬于內核核對象,,而臨界界段屬于于用戶方方式對象象。互斥量的的線程ID標識系統統中哪個個線程擁擁有互斥斥量,為為0,沒有線線程擁有有遞歸計數數器指明明線程擁擁有互斥斥量的次次數4、互斥量量經常用于于保護多多個線程程訪問的的內存塊塊;控制對共共享資源源的訪問問保證每次次只能有有一個線線程獲得得互斥量量4、互斥量量互斥量的的創建,,返回句句柄HANDLECreateMutex(PSECURITY_ATTRIBUTESpsa,//安全屬性性的指針針BOOLbInitialOwner,//初始化互互斥對象象的所有有者PCTSTRpszName//指向互互斥對對象名名的指指針);4、互斥斥量另一個個進程程可獲獲得本本進程程相關關的互互斥量量的句句柄HANDLEOpenMutex(DWORDfdwAccess,//accessBOOLbInheritHandle,//inheritanceoptionPCTSTRpszName//objectname);釋放互互斥量量HANDLEReleaseMutex(HANDLEhMutex);等待互互斥量量DWORDWaitForSingleObject(HANDLEhHandle,DWORDdwMilliseconds);互斥量量不同同于其其它內內核對對象,,互斥斥對象象有一一個““線程程所有4、互斥斥量#include<windows.h>#include<fstream>usingnamespacestd;fstreamfile;DWORDWINAPIThreadFunc1(PVOIDparam){HANDLE*phMutex=(HANDLE*)param;for(inti=1;i<=100;i++){WaitForSingleObject(*phMutex,INFINITE);file<<"ThreadFunc1Output"<<i<<endl;ReleaseMutex(*phMutex);}return0;}DWORDWINAPIThreadFunc2(PVOIDparam){HANDLE*phMutex=(HANDLE*)param;for(inti=1;i<=100;i++){WaitForSingleObject(*phMutex,INFINITE);file<<"ThreadFunc2Output"<<i<<endl;ReleaseMutex(*phMutex);}return0;}intmain(){file.open("data.txt",ios::out);HANDLEhMutex=CreateMutex(NULL,FALSE,"DisplayMutex");HANDLEThreadHandle1=CreateThread(NULL,0,ThreadFunc1,&hMutex,0,NULL);HANDLEThreadHandle2=CreateThread(NULL,0,ThreadFunc2,&hMutex,0,NULL);HANDLEhThread[2]={ThreadHandle1,ThreadHandle2};WaitForMultipleObjects(2,hThread,TRUE,INFINITE);CloseHandle(hMutex);file.close();return0;}5、信號量信號量是一一個內核對對象,可用用來管理大大量有限的的系統資源源一個使用計計數32位整數,最最大資源數數量32位整數,當當前資源數數量信號量使用用規則:當前資源數數量大于0,則等待信信號量的線線程獲得資資源繼續運運行,當前前資源數量量減1當前資源數數量等于0,則等待信信號量的線線程繼續等等待,直到到有線程釋釋放信號量量,使當前前資源數量量大于0創建信號量量5、信號量HANDLECreateSemaphore(PSECURITY_ATTRIBUTESpsa,LONGlInitialCount,//initialcountLONGlMaximumCount,//maximumcountPCTSTRpszName//objectname);另一進程可可獲得與本本進程相關關的信號量量的句柄5、信號量HANDLEOpenSemaphore(DWORDfdwAccess,BOOLbInheritHandle,//inheritanceoptionPCTSTRpszName//objectname);釋放信號量量例,兩個線線程分別有有一個初值值為0的Int型局部變量量,兩個線線程的行為為是在一個個循環中,,使整型變變量遞增,,一個約束束條件,在在遞增過程程中,這兩兩個值的差差不超過5ReleaseSemaphore(HANDLEhSem,LONGlReleaseCount,PLONGplPreviousCount);5、信號量HANDLEhsem1=CreateSemaphore(NULL,5,10,"sem1");HANDLEhsem2=CreateSemaphore(NULL,5,10,"sem2");inti1=0;inti2=0;DWORDWINAPIThreadFunc1(PVOIDparam){for(inti=1;i<=100;i++){WaitForSingleObject(hsem1,INFINITE);ReleaseSemaphore(hsem2,1,NULL);i1++;file<<"i1="<<i1<<"i2="<<i2<<endl;}return0;}DWORDWINAPIThreadFunc2(PVOIDparam){for(inti=1;i<=100;i++){WaitForSingleObject(hsem2,INFINITE);ReleaseSemaphore(hsem1,1,NULL);i2++;file<<"i1="<<i1<<"i2="<<i2<<endl;}return0;}線程的優先先級決定它它何時運行行和接收多多少CPU時間。優先級共32級,是從0到31的數值,稱稱為基本優優先級別。。0-15級是普通優優先級線程的優先先級可以動動態變化高優先級線線程優先運運行,只有有高優先級級線程不運運行時,才才調度低優優先級線程程運行。優先級相同同的線程按按照時間片片輪流運行行。進程與線程程的優先級級進程與線程程的優先級級16-31級是實時優優先級相同優先級級線程的運運行不按照照時間片輪輪轉,而是是先運行的的線程就先先控制CPU,如果它不

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論