版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、第二章 Windows多線程編程內(nèi)容1. Windows操作系統(tǒng)的一些基本知識操作系統(tǒng)的一些基本知識 2. Win32 API線程庫線程庫 3. 線程間通信線程間通信 1、Windows操作系統(tǒng)的一些基本知識操作系統(tǒng)的一些基本知識 1. API2. 內(nèi)核對象及句柄內(nèi)核對象及句柄API ( Application Programming Interface )nAPIAPI:操作系統(tǒng)留給應(yīng)用程序的一個調(diào)用接口,操作系統(tǒng)留給應(yīng)用程序的一個調(diào)用接口,應(yīng)用程序通過應(yīng)用程序通過APIAPI使操作系統(tǒng)去執(zhí)行使操作系統(tǒng)去執(zhí)行相應(yīng)相應(yīng)程序程序。nWindows APIWindows API是一套用來控制是一套
2、用來控制WindowsWindows的各個部件的各個部件的外觀和行為的預(yù)先定義的的外觀和行為的預(yù)先定義的WindowsWindows函數(shù)。函數(shù)。nWin32 APIWin32 API即為即為Microsoft 32Microsoft 32位平臺的應(yīng)用程序位平臺的應(yīng)用程序編程接口。編程接口。Win32Win32平臺上運行的應(yīng)用程序都可以平臺上運行的應(yīng)用程序都可以調(diào)用這些函數(shù)。調(diào)用這些函數(shù)。n3232與與6464位位APIAPI函數(shù)聲明上沒有明顯區(qū)別,但函數(shù)聲明上沒有明顯區(qū)別,但6464位位編程是需要下載相應(yīng)的編程是需要下載相應(yīng)的軟件開發(fā)包軟件開發(fā)包SDKSDK。 API ( Applicatio
3、n Programming Interface )n直接用直接用win32 APIwin32 API編寫的應(yīng)用程序,程序的執(zhí)行編寫的應(yīng)用程序,程序的執(zhí)行代碼小,運行效率高代碼小,運行效率高nMFCMFC用類庫的方式將用類庫的方式將 win32 API win32 API 進行封裝進行封裝, , 以類以類的方式提供給開發(fā)者的方式提供給開發(fā)者內(nèi)核對象及句柄n內(nèi)核對象是由操作系統(tǒng)內(nèi)核分配,內(nèi)核對象是由操作系統(tǒng)內(nèi)核分配,只能由內(nèi)核訪只能由內(nèi)核訪問的數(shù)據(jù)結(jié)構(gòu)問的數(shù)據(jù)結(jié)構(gòu),供系統(tǒng)和應(yīng)用程序使用來管理各供系統(tǒng)和應(yīng)用程序使用來管理各種系統(tǒng)資源種系統(tǒng)資源 。n內(nèi)核對象包括:內(nèi)核對象包括:進程對象、線程對象、事件
4、對象、進程對象、線程對象、事件對象、文件對象、作業(yè)對象、互斥對象、等待計時器對文件對象、作業(yè)對象、互斥對象、等待計時器對象等都是內(nèi)核對象。象等都是內(nèi)核對象。n出于安全的考慮,進程不能直接訪問內(nèi)核對象。出于安全的考慮,進程不能直接訪問內(nèi)核對象。n操作系統(tǒng)提供了一組函數(shù)來訪問內(nèi)核對象。通過操作系統(tǒng)提供了一組函數(shù)來訪問內(nèi)核對象。通過函數(shù)創(chuàng)建、打開和操作內(nèi)核對象。函數(shù)創(chuàng)建、打開和操作內(nèi)核對象。內(nèi)核對象及句柄n內(nèi)核對象由內(nèi)核擁有,各個進程可以共享內(nèi)核對內(nèi)核對象由內(nèi)核擁有,各個進程可以共享內(nèi)核對象。進程終止執(zhí)行,它使用的內(nèi)核對象并不一定象。進程終止執(zhí)行,它使用的內(nèi)核對象并不一定會被撤銷。會被撤銷。n每個內(nèi)
5、核對象都有一個計數(shù)器來存儲有多少個進每個內(nèi)核對象都有一個計數(shù)器來存儲有多少個進程在使用它的信息。程在使用它的信息。n進程調(diào)用時,計數(shù)器增進程調(diào)用時,計數(shù)器增1,調(diào)用結(jié)束,計數(shù)器減,調(diào)用結(jié)束,計數(shù)器減1。n內(nèi)核對象計數(shù)器為零時,銷毀此內(nèi)核對象。內(nèi)核對象計數(shù)器為零時,銷毀此內(nèi)核對象。 內(nèi)核對象及句柄n內(nèi)核對象有安全描述符的保護,安全描述符描述內(nèi)核對象有安全描述符的保護,安全描述符描述了誰創(chuàng)建了該對象以及誰能夠使用該對象。了誰創(chuàng)建了該對象以及誰能夠使用該對象。n用于創(chuàng)建內(nèi)核對象的函數(shù)幾乎都有一個指向用于創(chuàng)建內(nèi)核對象的函數(shù)幾乎都有一個指向SECURITY_ATTRIBUTES 結(jié)構(gòu)的指針作為其參結(jié)構(gòu)的
6、指針作為其參數(shù)。數(shù)。n 大多數(shù)應(yīng)用程序通過傳大多數(shù)應(yīng)用程序通過傳NULL值,創(chuàng)建具有默認(rèn)值,創(chuàng)建具有默認(rèn)安全性的對象。如果想限制其他線程對對象的訪安全性的對象。如果想限制其他線程對對象的訪問,就需要單獨創(chuàng)建一個問,就需要單獨創(chuàng)建一個SECURITY_ATTRIBUTES對象并對其初始化。對象并對其初始化。內(nèi)核對象及句柄n句柄:句柄:創(chuàng)建內(nèi)核對象時,函數(shù)的返回值,標(biāo)記該創(chuàng)建內(nèi)核對象時,函數(shù)的返回值,標(biāo)記該內(nèi)核對象。內(nèi)核對象。n句柄表:句柄表:進程被初始化時,系統(tǒng)給進程分配一個進程被初始化時,系統(tǒng)給進程分配一個句柄表,用于保存該進程使用的內(nèi)核對象的信息,句柄表,用于保存該進程使用的內(nèi)核對象的信息,
7、而句柄值則是相應(yīng)內(nèi)核對象在句柄表中的索引值,而句柄值則是相應(yīng)內(nèi)核對象在句柄表中的索引值,因此句柄值是進程相關(guān)的。因此句柄值是進程相關(guān)的。內(nèi)核對象及句柄n內(nèi)核對象創(chuàng)建內(nèi)核對象創(chuàng)建n當(dāng)利用當(dāng)利用creat*函數(shù)來創(chuàng)建內(nèi)核對象時,系統(tǒng)內(nèi)核就為該函數(shù)來創(chuàng)建內(nèi)核對象時,系統(tǒng)內(nèi)核就為該對象分配一個內(nèi)存塊,并進行初始化,然后系統(tǒng)內(nèi)核掃對象分配一個內(nèi)存塊,并進行初始化,然后系統(tǒng)內(nèi)核掃描該進程的句柄表,初始化一條記錄并放在句柄表中。描該進程的句柄表,初始化一條記錄并放在句柄表中。n關(guān)閉內(nèi)核對象關(guān)閉內(nèi)核對象n無論進程怎樣創(chuàng)建內(nèi)核對象,在不使用該對象的時候都無論進程怎樣創(chuàng)建內(nèi)核對象,在不使用該對象的時候都應(yīng)當(dāng)通過應(yīng)
8、當(dāng)通過Bool CloseHandle(HANDLE hobj)來向操作來向操作統(tǒng)聲明結(jié)束對該對象的訪問。統(tǒng)聲明結(jié)束對該對象的訪問。Win32 API線程庫線程庫 1. 創(chuàng)建線程的基本問題創(chuàng)建線程的基本問題2. 創(chuàng)建線程的創(chuàng)建線程的API函數(shù)函數(shù)3. 操作線程的操作線程的API4. 一個簡單的一個簡單的Windows多線程程序多線程程序1 創(chuàng)建線程的基本問題 n線程可以由進程中的任意線程創(chuàng)建,而進程的主線程在進線程可以由進程中的任意線程創(chuàng)建,而進程的主線程在進程加載時自動創(chuàng)建。程加載時自動創(chuàng)建。n每個線程都有自己的進入點函數(shù)。每個線程都有自己的進入點函數(shù)。n主線程的進入點函數(shù)主線程的進入點函數(shù)
9、進入點進入點應(yīng)用程序類型應(yīng)用程序類型WinMainWinMain需要需要ANSIANSI字符和字符串的字符和字符串的GUIGUI應(yīng)用程序應(yīng)用程序wWinMainwWinMain需要需要UnicodeUnicode字符和字符串的字符和字符串的GUIGUI應(yīng)用程序應(yīng)用程序MainMain需要需要ANSIANSI字符和字符串的字符和字符串的CUICUI應(yīng)用程序應(yīng)用程序WmainWmain需要需要UnicodeUnicode字符和字符串的字符和字符串的CUICUI應(yīng)用程序應(yīng)用程序 線程函數(shù)的返回值是該線程的退出代碼線程函數(shù)的返回值是該線程的退出代碼 線程函數(shù)應(yīng)盡可能使用函數(shù)參數(shù)和局部變量線程函數(shù)應(yīng)盡可
10、能使用函數(shù)參數(shù)和局部變量線程函數(shù)-線程的入口點DWORD WINAPI ThreadFunc ( PVOID pvParam ) DWORD dwResult = 0;return (dwResult);2 創(chuàng)建線程的API函數(shù)n創(chuàng)建線程過程:創(chuàng)建線程過程:n系統(tǒng)創(chuàng)建一個線程內(nèi)核對象。線程內(nèi)核對象不系統(tǒng)創(chuàng)建一個線程內(nèi)核對象。線程內(nèi)核對象不是線程本身,而是操作系統(tǒng)用來管理線程的較是線程本身,而是操作系統(tǒng)用來管理線程的較小的數(shù)據(jù)結(jié)構(gòu)。小的數(shù)據(jù)結(jié)構(gòu)。n在進程的地址空間分配內(nèi)存,供線程的堆棧使在進程的地址空間分配內(nèi)存,供線程的堆棧使用用HANDLE CreateThread(PSECURITY_ATT
11、RIBUTES psa, DWORD cbStack,PTHREAD_START_ROUTINE pStartAddr,PVOID pvParam, DWORD fdwCreate, PDWORD pdwThreadId); 2 創(chuàng)建線程的API函數(shù)NULL0函數(shù)地址函數(shù)地址函數(shù)參數(shù)函數(shù)參數(shù)NULL控制創(chuàng)建線程標(biāo)志控制創(chuàng)建線程標(biāo)志CREATE_SUSPENDED0線程線程ID#include windows.h#include using namespace std;DWORD WINAPI ThreadFunc(PVOID pvParam)coutCreated thread says he
12、llo World!endl;return 0;int main()HANDLE ThreadHandle = CreateThread(NULL,0,ThreadFunc,NULL,0,NULL);Sleep(100);coutMain thread says Hello World!endl;getchar();return 0;n暫停線程暫停線程DWORD DWORD SuspendThread(HANDLESuspendThread(HANDLE hThreadhThread) )n返回值是線程的前一個暫停計數(shù)返回值是線程的前一個暫停計數(shù)n暫停計數(shù):是線程內(nèi)核對象的一個內(nèi)部值。暫停計數(shù)
13、:是線程內(nèi)核對象的一個內(nèi)部值。n使用要小心,因為不知道暫停線程運行時它在進使用要小心,因為不知道暫停線程運行時它在進行什么操作??赡茉斐伤梨i行什么操作。可能造成死鎖3 操作線程的API3 操作線程的APIn恢復(fù)線程恢復(fù)線程DWORD DWORD ResumeThread(HANDLEResumeThread(HANDLE hThreadhThread); ); n返回值是線程的前一個暫停計數(shù)返回值是線程的前一個暫停計數(shù)n該函數(shù)用于將處于暫停狀態(tài)的線程置于就該函數(shù)用于將處于暫停狀態(tài)的線程置于就緒狀態(tài),使其參加線程調(diào)度。緒狀態(tài),使其參加線程調(diào)度。3 操作線程的APIn使線程睡眠使線程睡眠VOID
14、Sleep (DWORD VOID Sleep (DWORD dwMillisecondsdwMilliseconds ); );n該函數(shù)是線程暫停自己的運行,直到睡眠時間過該函數(shù)是線程暫停自己的運行,直到睡眠時間過去為止。去為止。n當(dāng)線程調(diào)用這個函數(shù)時,它自動放棄剩余的時間當(dāng)線程調(diào)用這個函數(shù)時,它自動放棄剩余的時間片,迫使系統(tǒng)進行線程調(diào)度。片,迫使系統(tǒng)進行線程調(diào)度。nWindowsWindows不是實時的操作系統(tǒng)。不是實時的操作系統(tǒng)。3 操作線程的APIn終止線程終止線程 線程函數(shù)返回(最好)線程函數(shù)返回(最好) 通過調(diào)用通過調(diào)用ExitThreadExitThread函數(shù),線程將自行撤銷函
15、數(shù),線程將自行撤銷 同一個進程或另一個進程中的線程調(diào)用同一個進程或另一個進程中的線程調(diào)用TerminateThreadTerminateThread函數(shù)函數(shù) 包含線程的進程終止包含線程的進程終止 線程返回函數(shù)線程返回函數(shù)n線程中創(chuàng)建的線程中創(chuàng)建的C+C+類對象能夠正常撤銷;類對象能夠正常撤銷;n操作系統(tǒng)將正確地釋放線程堆棧使用的內(nèi)操作系統(tǒng)將正確地釋放線程堆棧使用的內(nèi)存;存;n系統(tǒng)將線程的退出代碼設(shè)置為線程函數(shù)的系統(tǒng)將線程的退出代碼設(shè)置為線程函數(shù)的返回值;返回值;n系統(tǒng)將遞減線程內(nèi)核對象的使用計數(shù)。系統(tǒng)將遞減線程內(nèi)核對象的使用計數(shù)。n線程調(diào)用這個函數(shù),強制線程終止運行;線程調(diào)用這個函數(shù),強制線程
16、終止運行;n操作系統(tǒng)清除該線程使用的所有系統(tǒng)資源。操作系統(tǒng)清除該線程使用的所有系統(tǒng)資源。nC+C+類對象將不被撤銷。類對象將不被撤銷。VOID VOID ExitThread(DWORDExitThread(DWORD dwExitCodedwExitCode); ); ExitThreadExitThread函數(shù)函數(shù)n能夠撤銷任何線程;能夠撤銷任何線程;n線程的內(nèi)核對象的使用計數(shù)也被遞減;線程的內(nèi)核對象的使用計數(shù)也被遞減;n異步運行的函數(shù);異步運行的函數(shù);n不撤銷線程的堆棧,直到進程終止。不撤銷線程的堆棧,直到進程終止。BOOL BOOL TerminateThread(HANDLETerm
17、inateThread(HANDLE hThread,DWORDhThread,DWORD dwExitCodedwExitCode); ); TerminateThreadTerminateThread函數(shù)函數(shù) 在進程終止運行時撤銷線程nExitProcessExitProcess 和和 TerminateProcessTerminateProcess函數(shù)可以終止線程,函數(shù)可以終止線程,將會終止進程中的所有線程;將會終止進程中的所有線程;nExitProcessExitProcess只能強制執(zhí)行本進程的退出;只能強制執(zhí)行本進程的退出;nTerminateProcessTerminatePro
18、cess在一個進程中強制結(jié)束其他的進程;在一個進程中強制結(jié)束其他的進程; n進程所使用的資源被清除;進程所使用的資源被清除;nC+C+對象撤銷函數(shù)沒有被調(diào)用。對象撤銷函數(shù)沒有被調(diào)用。VOID VOID ExitProcess(UINTExitProcess(UINT uExitCodeuExitCode); ); BOOL BOOL TerminateProcess(HANDLETerminateProcess(HANDLE hProcesshProcess, UINT , UINT uExitCodeuExitCode); ); #include #include using namespa
19、ce std;DWORD WINAPI FunOne(LPVOID param)int* p=(int*)param;cout(*p)endl; while(true) Sleep(1000); couthello! ; return 0; DWORD WINAPI FunTwo(LPVOID param)int* p=(int*)param;cout(*p)endl; while(true) Sleep(1000); coutinput; if(input=1) ResumeThread(hand1);ResumeThread(hand2); else SuspendThread(hand1
20、);SuspendThread(hand2); TerminateThread(hand1,1); TerminateThread(hand2,1); return 0;例例n打印出打印出1001000之間的所有之間的所有“水仙花數(shù)水仙花數(shù)”,所謂,所謂“水仙花數(shù)水仙花數(shù)”是指一個三位數(shù),其是指一個三位數(shù),其各位數(shù)字立方和等于該數(shù)本身。各位數(shù)字立方和等于該數(shù)本身。n例如:例如:153是一個是一個“水仙花數(shù)水仙花數(shù)”,因為,因為153=13+33+53n不需要通信不需要通信int main( )int i,j,k,n;printf(水仙花數(shù)水仙花數(shù)是是:);for(n=100;nlow;int
21、high = bou-high;for(n=low;nhigh;n+)i=n/100;j=n/10-i*10;k=n%10;if(i*100+j*10+k=i*i*i+j*j*j+k*k*k)printf(%d ,n);return 0;int main( )printf(水仙花數(shù)水仙花數(shù)是是:);bound qw1,qw2;qw1.low=100;qw1.high =500; HANDLE ThreadHandle1= CreateThread(NULL,0,Thread1,&qw1,0,NULL);qw2.low=500;qw2.high=1000;HANDLE ThreadHan
22、dle2 = CreateThread(NULL,0,Thread1,&qw2,0,NULL);HANDLE ThreadHandles2= ThreadHandle1,ThreadHandle2;WaitForMultipleObjects(2,ThreadHandles,TRUE,INFINITE);return 0;線程間通信n操作系統(tǒng)隨機調(diào)度線程,程序員不能預(yù)知線程的執(zhí)行順序操作系統(tǒng)隨機調(diào)度線程,程序員不能預(yù)知線程的執(zhí)行順序n下面兩種情況下,線程間需要通信下面兩種情況下,線程間需要通信n當(dāng)有多個線程訪問共享資源而不希望共享資源遭到破當(dāng)有多個線程訪問共享資源而不希望共享資源遭到破
23、壞;(互斥)壞;(互斥)n當(dāng)一個線程需要將某個任務(wù)已經(jīng)完成的情況通知另外當(dāng)一個線程需要將某個任務(wù)已經(jīng)完成的情況通知另外一個或多個線程時。(同步)一個或多個線程時。(同步)nWindowsWindows線程通信方法主要有互鎖函數(shù)、臨界段、線程通信方法主要有互鎖函數(shù)、臨界段、事件、事件、互斥量、信號量互斥量、信號量線程間通信1.1.互鎖函數(shù)互鎖函數(shù)2.2.臨界段臨界段3.3.事件事件4.4.互斥量互斥量5.5.信號量信號量使用內(nèi)核對象的線程間通信n互鎖函數(shù)和臨界段都是在用戶態(tài)實現(xiàn)線程通信的,互鎖函數(shù)和臨界段都是在用戶態(tài)實現(xiàn)線程通信的,優(yōu)點速度快優(yōu)點速度快n用戶態(tài)機制只能實現(xiàn)同一進程內(nèi)線程通信。用戶
24、態(tài)機制只能實現(xiàn)同一進程內(nèi)線程通信。n內(nèi)核對象機制可以實現(xiàn)不同進程內(nèi)線程的通信,缺內(nèi)核對象機制可以實現(xiàn)不同進程內(nèi)線程的通信,缺點速度慢。點速度慢。n包含通知狀態(tài)和未通知狀態(tài)內(nèi)核屬性包含通知狀態(tài)和未通知狀態(tài)內(nèi)核屬性的內(nèi)核對象有:的內(nèi)核對象有:n進程,線程進程,線程,作業(yè),文件,控制臺輸入,作業(yè),文件,控制臺輸入n文件修改通知,事件,可等待定時器文件修改通知,事件,可等待定時器n信號量,互斥量信號量,互斥量n等待函數(shù):使線程進入等待狀態(tài)等待函數(shù):使線程進入等待狀態(tài), ,直到一直到一個對象變?yōu)橐淹ㄖ獱顟B(tài)。個對象變?yōu)橐淹ㄖ獱顟B(tài)。DWORD WaitForSingleObject( HANDLE hHan
25、dle, DWORD dwMilliseconds ); 參數(shù)參數(shù)dwMillisecondsdwMilliseconds有兩個特殊值:有兩個特殊值:0 0,則該函數(shù)立即返回;,則該函數(shù)立即返回;INFINITEINFINITE,則線程被掛起,直到,則線程被掛起,直到hHandlehHandle所指向的對所指向的對象變?yōu)橐淹ㄖ獱顟B(tài)。象變?yōu)橐淹ㄖ獱顟B(tài)。 使用內(nèi)核對象的線程間通信n等待函數(shù):等待函數(shù):可以保證線程的同步可以保證線程的同步 。DWORD WaitForMultipleObject( DWORD dwCount,CONST HANDLE* phHandle, BOOL fWaitAll
26、,DWORD dwMilliseconds ); 使用內(nèi)核對象的線程間通信1、互鎖函數(shù)n互鎖函數(shù)是用來解決原子訪問的,主要針對變量互鎖函數(shù)是用來解決原子訪問的,主要針對變量的原子訪問;的原子訪問;n原子訪問:當(dāng)線程訪問資源時,能夠確保沒有其原子訪問:當(dāng)線程訪問資源時,能夠確保沒有其它線程同時訪問相同的資源。它線程同時訪問相同的資源。Long g_x = 0; /全局變量全局變量DWORD WINAPI ThreadFunc1 (PVOID pvParam) g_x+;return 0; DWORD WINAPI ThreadFunc2 (PVOID pvParam) g_x+;return 0
27、; MOV EAX, g_xINC EAXMOV g_x, EAX遞增以原子方式運行遞增以原子方式運行1、互鎖函數(shù)(例)1、互鎖函數(shù)LONG InterlockedExchangeAdd()( PLONG plAddend, LONG lIncrement);Long g_x=0; /全局變量全局變量DWORD WINAPI ThreadFunc1 (PVOID pvParam) InterlockedExchangeAdd(&g_x,1);return 0; DWORD WINAPI ThreadFunc2 (PVOID pvParam) InterlockedExchangeAdd
28、(&g_x,1);return 0; 1、互鎖函數(shù)n以原子操作方式用第二個參數(shù)的值取代第以原子操作方式用第二個參數(shù)的值取代第一個參數(shù)的當(dāng)前值。一個參數(shù)的當(dāng)前值。LONG InterlockedExchange ()( PLONG plTarget, LONG lValue);LONG InterlockedExchangePointer ()( PVOID* ppvTarget, PVOID pvValue);1、互鎖函數(shù)n比較第一個參數(shù)所指的值和第三個參數(shù)的值,如比較第一個參數(shù)所指的值和第三個參數(shù)的值,如果相等,則將第一個參數(shù)所指的值置為第二個參果相等,則將第一個參數(shù)所指的值置為第二
29、個參數(shù),如果不相等則不進行任何操作。數(shù),如果不相等則不進行任何操作。LONG LONG InterlockedCompareExchangeInterlockedCompareExchange ()( ()( PLONG PLONG plDestinationplDestination, LONG , LONG lExchangelExchange, LONG , LONG lComparandlComparand););LONG LONG InterlockedCompareExchangePointerInterlockedCompareExchangePointer ()( ()( PV
30、OID PVOID* * ppvDestinationppvDestination, PVOID , PVOID pvExchangepvExchange, PVOID , PVOID pvComparandpvComparand););例:例:10000個個2相加相加int main( )int sum=0;for(int i=1;i=10000; i+)sum=sum+2;printf(10000個個2相加之和是相加之和是 %d,sum);getchar();return 0;#include windows.hlong sum=0;DWORD WINAPI Thread1(PVOID p
31、vParam)for(int i=1;i=5000; i+)/InterlockedExchangeAdd(&sum,2);sum=sum+2;return 0;DWORD WINAPI Thread2(PVOID pvParam)for(int i=5001;i=10000; i+)/InterlockedExchangeAdd(&sum,2);sum=sum+2;return 0;int main()HANDLE ThreadHandle1 = CreateThread(NULL,0,Thread1,NULL,0,NULL);HANDLE ThreadHandle2 = C
32、reateThread(NULL,0,Thread2,NULL,0,NULL);HANDLE ThreadHandles2= ThreadHandle1,ThreadHandle2;WaitForMultipleObjects(2,ThreadHandles,TRUE,INFINITE);printf(10000個個2相加之和是相加之和是 %d,sum);getchar();return 0;2、臨界段n互鎖函數(shù):以原子操作方式修改單個值互鎖函數(shù):以原子操作方式修改單個值n臨界段:以原子方式修改復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。臨界段:以原子方式修改復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。n臨界段:關(guān)鍵代碼段,是指一小段代碼,同臨界段
33、:關(guān)鍵代碼段,是指一小段代碼,同一個時刻,只能有一個線程具有訪問權(quán)。一個時刻,只能有一個線程具有訪問權(quán)。n多個線程訪問同一個臨界區(qū)的原則:多個線程訪問同一個臨界區(qū)的原則:n 一次最多只能一個線程停留在臨界區(qū)內(nèi);一次最多只能一個線程停留在臨界區(qū)內(nèi);n 不能讓一個線程無限地停留在臨界區(qū)內(nèi),否則不能讓一個線程無限地停留在臨界區(qū)內(nèi),否則其它線程將不能進入該臨界區(qū)其它線程將不能進入該臨界區(qū) 2、臨界段 相關(guān)API函數(shù) n首先定義一個臨界段對象(通常全局變量)首先定義一個臨界段對象(通常全局變量)CRITICAL_SECTION CRITICAL_SECTION cscsn臨界段對象初始化臨界段對象初始化
34、InitializeCriticalSectionInitializeCriticalSection (& (&cscs)n進入臨界段進入臨界段EnterCriticalSectionEnterCriticalSection (& (&cscs) )n離開臨界段離開臨界段LeaveCriticalSectionLeaveCriticalSection (& (&cscs) )n釋放臨界段對象釋放臨界段對象DeleteCriticalSectionDeleteCriticalSection (& (&cscs) )臨界段 例1#in
35、clude #include fstream file;DWORD WINAPI ThreadFunc1(PVOID param)for(int i=1;i=1000;i+)fileThreadFunc1 Outputiendl;return 0;DWORD WINAPI ThreadFunc2(PVOID param) for(int i=1;i=1000;i+)fileThreadFunc2 Outputiendl;return 0;int main() file.open(data.txt,ios:out);HANDLE ThreadHandle1 = CreateThread(NULL
36、,0,ThreadFunc1,NULL,0,NULL);HANDLE ThreadHandle2 = CreateThread(NULL,0,ThreadFunc2,NULL,0,NULL);HANDLE hThread2 = ThreadHandle1,ThreadHandle2;WaitForMultipleObjects(2,hThread,TRUE,INFINITE);file.close();return 0;加上臨界段#include #include fstream file;CRITICAL_SECTION cs;DWORD WINAPI ThreadFunc1(PVOID p
37、aram)for(int i=1;i=1000;i+)EnterCriticalSection (&cs);fileThreadFunc1 Outputiendl;LeaveCriticalSection (&cs);return 0;DWORD WINAPI ThreadFunc2(PVOID param) for(int i=1;i=1000;i+)EnterCriticalSection (&cs);fileThreadFunc2 Outputiendl;LeaveCriticalSection (&cs);return 0;#include “windo
38、ws.h“ 例例2CRITICAL_SECTION g_cs;char g_cArray10; / 共享資源共享資源 DWORD WINAPI ThreadProc1(PVOID pParam)EnterCriticalSection(&g_cs);/ 對共享資源進行寫入操作對共享資源進行寫入操作for (int i = 0; i 10; i+)g_cArrayi = a;Sleep(1);LeaveCriticalSection(&g_cs);return 0;DWORD WINAPI ThreadProc2(PVOID pParam)/ 進入臨界區(qū)進入臨界區(qū)EnterCri
39、ticalSection(&g_cs);/ 對共享資源進行寫入操作對共享資源進行寫入操作for (int i = 0; i 10; i+)g_cArray10 - i - 1 = b;Sleep(1);/ 離開臨界區(qū)離開臨界區(qū)LeaveCriticalSection(&g_cs);return 0;int main()InitializeCriticalSection(&g_cs);HANDLE ThreadHandle1 = CreateThread(NULL,0,ThreadProc1,NULL,0,NULL);HANDLE ThreadHandle2 = Crea
40、teThread(NULL,0,ThreadProc2,NULL,0,NULL);HANDLE ThreadHandles2= ThreadHandle1,ThreadHandle2;WaitForMultipleObjects(2,ThreadHandles,TRUE,INFINITE);DeleteCriticalSection(&g_cs);printf(g_cArray);getchar();return 0;3、事件n事件內(nèi)核對象是最簡單的對象。事件內(nèi)核對象是最簡單的對象。n一個使用計數(shù)一個使用計數(shù)n一個布爾值,指明該事件是自動復(fù)位事件一個布爾值,指明該事件是自動復(fù)位事件(f
41、alse)(false),還是人工復(fù)位事件,還是人工復(fù)位事件(true)(true);n一個布爾值,指明該事件是已通知狀態(tài)一個布爾值,指明該事件是已通知狀態(tài)(true)(true),還是未通知狀態(tài)還是未通知狀態(tài)(false)(false) 。 n當(dāng)人工復(fù)位事件得到通知時,等待該事件的所有當(dāng)人工復(fù)位事件得到通知時,等待該事件的所有線程均變?yōu)榭烧{(diào)度事件;線程均變?yōu)榭烧{(diào)度事件;n當(dāng)自動復(fù)位事件得到通知時,等待該事件的線程當(dāng)自動復(fù)位事件得到通知時,等待該事件的線程中只有一個線程變?yōu)榭烧{(diào)度線程。中只有一個線程變?yōu)榭烧{(diào)度線程。 n創(chuàng)建事件內(nèi)核對象,返回句柄。創(chuàng)建事件內(nèi)核對象,返回句柄。 HANDLE HA
42、NDLE CreateEventCreateEvent( ( PSECURITY_ATTRIBUTES PSECURITY_ATTRIBUTES psapsa, / , / 安全屬性安全屬性 BOOL BOOL fManualResetfManualReset, /, /復(fù)位方式復(fù)位方式 BOOL BOOL fInitialStatefInitialState, / , / 初始狀態(tài)初始狀態(tài) PCTSTR PCTSTR pszNamepszName / / 對象名稱對象名稱 ); ); 3、事件n打開一個已經(jīng)存在的命名事件對象打開一個已經(jīng)存在的命名事件對象 HANDLE HANDLE Open
43、EventOpenEvent( ( DWORD DWORD f fdwAccessdwAccess, , BOOL BOOL f fInheritInherit, , PCTSTR PCTSTR pszpszNameName ); ); 3、事件EVENT_ALL_ACCESS 要求對事件對象進行完全訪問EVENT_MODIFY_STATE 允許SetEvent 和 ResetEvent函數(shù)SYNCHRONIZE 允許事件對象的使用同步 n一旦事件已經(jīng)創(chuàng)建,就可以直接控制它的狀態(tài)一旦事件已經(jīng)創(chuàng)建,就可以直接控制它的狀態(tài)n將事件設(shè)置為已通知狀態(tài)將事件設(shè)置為已通知狀態(tài)BOOL BOOL SetEv
44、ent(HANDLESetEvent(HANDLE hEventhEvent ); ); n將事件設(shè)置為未通知狀態(tài)將事件設(shè)置為未通知狀態(tài)BOOL BOOL ResetEvent(HANDLEResetEvent(HANDLE hEventhEvent ); );3、事件3、事件n事件的主要用途是標(biāo)志事件的發(fā)生,并以事件的主要用途是標(biāo)志事件的發(fā)生,并以此協(xié)調(diào)線程的執(zhí)行順序。此協(xié)調(diào)線程的執(zhí)行順序。n例例1:用戶在主線程輸入命令,控制新建線:用戶在主線程輸入命令,控制新建線程的運行。程的運行。#include #include #include using namespace std;CRITICA
45、L_SECTION cs;DWORD WINAPI ThreadFunc(PVOID param) EnterCriticalSection (&cs); coutCreate Thread: Create thread is startedendl; coutCreate Thread: Create thread is waiting continue command.endl; LeaveCriticalSection (&cs); HANDLE phEvent = OpenEvent(EVENT_ALL_ACCESS,TRUE,ContinueCommand); Wai
46、tForSingleObject(phEvent,INFINITE); coutCreate Thread: Recieved continue command.endl; coutCreate Thread: Thread runs again.endl; Sleep(2000); coutCreate Thread: Thread finished.endl; return 0;例例1int main()InitializeCriticalSection (&cs);HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,ContinueComma
47、nd);coutMain Thread: Creating new thread.endl;HANDLE ThreadHandle = CreateThread(NULL,0,ThreadFunc,NULL,CREATE_SUSPENDED,NULL);coutMain Thread: New thread created.endl;ResumeThread(ThreadHandle);string input;while(TRUE)EnterCriticalSection (&cs);coutMain Thread: input command, pleaseendl;LeaveCr
48、iticalSection (&cs);cout;cininput;if(input=continue)coutMain Thread: Let thread continue runendl;SetEvent(hEvent);break;WaitForSingleObject(ThreadHandle,INFINITE);coutMain Thread: Create thread finishedendl;DeleteCriticalSection (&cs);CloseHandle(hEvent);return 0;例2n設(shè)計簡單的文字管理軟件,要求實現(xiàn)功能設(shè)計簡單的文字
49、管理軟件,要求實現(xiàn)功能,讀文件、字?jǐn)?shù)統(tǒng)計、拼寫檢查、語法檢,讀文件、字?jǐn)?shù)統(tǒng)計、拼寫檢查、語法檢查查#include HANDLE g_hEvent; void OpenFileAndReadContentsIntoMemory() printf(Open File and Read contents into memoryn);DWORD WINAPI WordCount(PVOID pvParam) WaitForSingleObject(g_hEvent, INFINITE); printf(0:word countn); SetEvent(g_hEvent); /自動自動 return(
50、0);DWORD WINAPI SpellCheck(PVOID pvParam) WaitForSingleObject(g_hEvent, INFINITE); printf(1:Spell checkn); /Access the memory block. SetEvent(g_hEvent); /自動自動 return(0);DWORD WINAPI GrammarCheck(PVOID pvParam) WaitForSingleObject(g_hEvent, INFINITE); printf(2:Grammar checkn); /Access the memory bloc
51、k. SetEvent(g_hEvent); /自動自動 return(0);int main()/ g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /人工重置人工重置 g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); /自動重置自動重置 HANDLE hThread3; DWORD dwThreadID3; hThread0 = CreateThread(NULL, 0, WordCount, NULL, 0, &dwThreadID0); hThread1 = CreateThrea
52、d(NULL, 0, SpellCheck, NULL, 0, &dwThreadID1); hThread2 = CreateThread(NULL, 0, GrammarCheck, NULL, 0, &dwThreadID2); OpenFileAndReadContentsIntoMemory(); /Allow all 3 threads to access the memory. SetEvent(g_hEvent); WaitForMultipleObjects (3, hThread, TRUE, INFINITE); printf(main thread ex
53、itn); getchar(); return 0;例3:協(xié)調(diào)兩個線程執(zhí)行順序n讀操作、寫操作讀操作、寫操作n先寫后讀先寫后讀HANDLE evRead, evFinish;DWORD WINAPI ReadThread(PVOID param)WaitForSingleObject (evRead ,INFINITE);coutReadingendl;SetEvent (evFinish);DWORD WINAPI WriteThread(PVOID param)coutWritingendl;SetEvent (evRead);int main()evRead = CreateEvent
54、(NULL ,FALSE ,FALSE ,NULL) ;evFinish = CreateEvent (NULL ,FALSE ,FALSE ,NULL) ; CreateThread(NULL,0, ReadThread,NULL,0,NULL); CreateThread(NULL,0, WriteThread,NULL,0,NULL);WaitForSingleObject (evFinish,INFINITE) ;coutThe Program is Endendl;return 0 ;4、互斥量n互斥量是一個種內(nèi)核對象,確保線程擁有對互斥量是一個種內(nèi)核對象,確保線程擁有對單個資源的互
55、斥訪問權(quán)。單個資源的互斥訪問權(quán)。n一個使用數(shù)量一個使用數(shù)量n一個線程一個線程IDn一個遞歸計數(shù)器一個遞歸計數(shù)器n互斥量的線程互斥量的線程ID標(biāo)識系統(tǒng)中哪個線程擁有互標(biāo)識系統(tǒng)中哪個線程擁有互斥量,為斥量,為0,沒有線程擁有,沒有線程擁有n遞歸計數(shù)器指明線程擁有互斥量的次數(shù)遞歸計數(shù)器指明線程擁有互斥量的次數(shù)4、互斥量n經(jīng)常用于保護多個線程訪問的內(nèi)存塊;經(jīng)常用于保護多個線程訪問的內(nèi)存塊;n控制對共享資源的訪問控制對共享資源的訪問 n保證每次只能有一個線程獲得互斥量保證每次只能有一個線程獲得互斥量 4、互斥量n互斥量的創(chuàng)建,返回句柄互斥量的創(chuàng)建,返回句柄 HANDLE CreateMutex( PSE
56、CURITY_ATTRIBUTES psa, / 安全屬性的指針安全屬性的指針 BOOL bInitialOwner, / 初始化互斥對象的所有者初始化互斥對象的所有者 PCTSTR pszName / 指向互斥對象名的指針指向互斥對象名的指針 ); InitialOwner:FALSE,互斥對象的線程ID和遞歸計數(shù)器均被設(shè)置為0。TRUE,互斥對象的線程ID被設(shè)置為調(diào)用線程的ID,遞歸計數(shù)器被設(shè)置為1。4、互斥量n為現(xiàn)有的一個已命名互斥對象創(chuàng)建一個新句柄為現(xiàn)有的一個已命名互斥對象創(chuàng)建一個新句柄 HANDLE OpenMutex( DWORD fdwAccess, / access BOOL
57、bInheritHandle, / inheritance option PCTSTR pszName / object name ); MUTEX_ALL_ACCESS 請求對互斥對象的完全訪問MUTEX_MODIFY_STATE 允許使用 ReleaseMutex 函數(shù)SYNCHRONIZE 允許使用互斥對象同步n釋放互斥量釋放互斥量 HANDLE HANDLE ReleaseMutexReleaseMutex( ( HANDLE HANDLE hMutexhMutex); ); n等待互斥量等待互斥量DWORD DWORD WaitForSingleObjectWaitForSingle
58、Object( ( HANDLE HANDLE hHandlehHandle, , DWORD DWORD dwMillisecondsdwMilliseconds ););n互斥量不同于其它內(nèi)核對象,互斥對象有一個互斥量不同于其它內(nèi)核對象,互斥對象有一個“線程所有線程所有權(quán)權(quán)”的概念。的概念。4、互斥量#include #include using namespace std;fstream file;DWORD WINAPI ThreadFunc1(PVOID param)HANDLE *phMutex=(HANDLE *)param;for(int i=1;i=100;i+)WaitFo
59、rSingleObject(*phMutex,INFINITE);fileThreadFunc1 Outputiendl;ReleaseMutex(*phMutex); return 0;例例1DWORD WINAPI ThreadFunc2(PVOID param) HANDLE *phMutex=(HANDLE *)param;for(int i=1;i=100;i+)WaitForSingleObject(*phMutex,INFINITE);fileThreadFunc2 Outputiendl;ReleaseMutex(*phMutex); return 0;int main()fi
60、le.open(data.txt,ios:out);HANDLE hMutex = CreateMutex(NULL,FALSE,DisplayMutex);HANDLE ThreadHandle1 = CreateThread(NULL,0,ThreadFunc1,&hMutex,0,NULL);HANDLE ThreadHandle2 = CreateThread(NULL,0,ThreadFunc2,&hMutex,0,NULL);HANDLE hThread2 = ThreadHandle1,ThreadHandle2;WaitForMultipleObjects(2,hThread,TRUE,INFINITE);CloseHandle(hMutex);file.close();return 0;比較臨界區(qū)、互斥量、事件n給數(shù)組元素賦值,并在屏幕打印出來給數(shù)組元素賦值,并在屏幕打印出來n改變起始值,無限重復(fù)上述過程改變起始值,無限重復(fù)上述過程#incl
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年紹興市上虞區(qū)中醫(yī)醫(yī)院醫(yī)共體招聘編外人員5人模擬筆試試題及答案解析
- 2025年福建泉州惠安縣宏福殯儀服務(wù)有限公司招聘5人參考考試試題及答案解析
- 2025年杭州市上城區(qū)閘弄口街道社區(qū)衛(wèi)生服務(wù)中心招聘編外1人考試參考試題及答案解析
- 深度解析(2026)GBT 26103.5-2010NGCLZ型帶制動輪鼓形齒式聯(lián)軸器
- 2025浙江寧波市象山半邊山紫冠投資有限公司酒店管理分公司(寧波象山海景皇冠假日酒店)招聘3人參考考試題庫及答案解析
- 深度解析(2026)《GBT 25982-2024客車車內(nèi)噪聲限值及測量方法》(2026年)深度解析
- 2025四川德陽市旌陽區(qū)孝泉鎮(zhèn)衛(wèi)生院(旌陽區(qū)第二人民醫(yī)院)招聘2人備考筆試題庫及答案解析
- 深度解析(2026)《GBT 25796-2010反應(yīng)艷黃W-2G(C.I.反應(yīng)黃39)》
- 深度解析(2026)《GBT 25734-2010牦牛肉干》(2026年)深度解析
- 深度解析(2026)《GBT 25688.2-2010土方機械 維修工具 第2部分:機械式拉拔器和推拔器》
- 2025至2030中國聚四氟乙烯(PTFE)行業(yè)經(jīng)營狀況及投融資動態(tài)研究報告
- 教育、科技、人才一體化發(fā)展
- 營銷與客戶關(guān)系管理-深度研究
- 耐壓試驗操作人員崗位職責(zé)
- 2020-2021學(xué)年廣東省廣州市黃埔區(qū)二年級(上)期末數(shù)學(xué)試卷
- 財政部政府采購法律法規(guī)與政策學(xué)習(xí)知識考試題庫(附答案)
- 長鑫存儲在線測評題
- DL∕T 5344-2018 電力光纖通信工程驗收規(guī)范
- T-CCIIA 0004-2024 精細(xì)化工產(chǎn)品分類
- 世界當(dāng)代史教材
- 高壓電動機保護原理及配置
評論
0/150
提交評論