windows多线程同步--临界区
推薦參考博客:秒殺多線程第五篇 經典線程同步 關鍵段CS
?
關于臨界區的觀念,一般操作系統書上面都有。
適用范圍:它只能同步一個進程中的線程,不能跨進程同步。一般用它來做單個進程內的代碼快同步,效率比較高
windows中與臨界區有關的結構是 CRITICAL_SECTION,關于該結構體的內部結構可參考here
使用時,主線程中要先初始化臨界區,最后要刪除臨界區,具體使用見下面代碼:
????????????????????????????????????????????????????????????????????????????? 本文地址
從一個例子來說明:假設有三個線程都需要使用打印機,我們可以把打印的代碼放到臨界區,這樣就可以保證每次只有一個線程在使用打印機。
?
#include<string>#include<iostream>#include<process.h>#include<windows.h>using namespace std;//定義一個臨界區CRITICAL_SECTION g_cs;//線程綁定的函數返回值和參數是確定的,而且一定要__stdcall unsigned __stdcall threadFun(void *param) {EnterCriticalSection(&g_cs);//進入臨界區,如果有其他線程則等待cout<<*(string *)(param)<<endl;LeaveCriticalSection(&g_cs);//退出臨界區,其他線程可以進來了return 1; }int main() {//初始化臨界區InitializeCriticalSection(&g_cs);HANDLE hth1, hth2, hth3;string s1 = "first", s2 = "second", s3 = "third";//創建線程hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s1, 0, NULL);hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s2, 0, NULL);hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFun, &s3, 0, NULL);//等待子線程結束WaitForSingleObject(hth1, INFINITE);WaitForSingleObject(hth2, INFINITE);WaitForSingleObject(hth3, INFINITE);//一定要記得關閉線程句柄CloseHandle(hth1);CloseHandle(hth2);CloseHandle(hth3);//刪除臨界區DeleteCriticalSection(&g_cs); }?
再看另外一個問題:編寫一個程序,開啟3個線程,這3個線程的ID分別為A、B、C,每個線程將自己的ID在屏幕上打印10遍,要求輸出結果必須按ABC的順序顯示;如:ABCABC….依次遞推, 仿照文章windows多線程同步--信號量中的代碼,我們把信號量替換成臨界區。
#include<string>#include<iostream>#include<process.h>#include<windows.h>using namespace std;//聲明3個臨界區 CRITICAL_SECTION g_cs1, g_cs2, g_cs3;//線程綁定的函數返回值和參數是確定的,而且一定要__stdcall unsigned __stdcall threadFunA(void *) {for(int i = 0; i < 10; i++){EnterCriticalSection(&g_cs1);//進入臨界區cout<<"A";LeaveCriticalSection(&g_cs2);//離開臨界區}return 1; } unsigned __stdcall threadFunB(void *) {for(int i = 0; i < 10; i++){EnterCriticalSection(&g_cs2);//進入臨界區cout<<"B";LeaveCriticalSection(&g_cs3);//離開臨界區}return 2; } unsigned __stdcall threadFunC(void *) {for(int i = 0; i < 10; i++){EnterCriticalSection(&g_cs3);//進入臨界區cout<<"C";LeaveCriticalSection(&g_cs1);//離開臨界區}return 3; }int main() {//初始化臨界區InitializeCriticalSection(&g_cs1);InitializeCriticalSection(&g_cs2);InitializeCriticalSection(&g_cs3);HANDLE hth1, hth2, hth3;//創建線程hth1 = (HANDLE)_beginthreadex(NULL, 0, threadFunA, NULL, 0, NULL);hth2 = (HANDLE)_beginthreadex(NULL, 0, threadFunB, NULL, 0, NULL);hth3 = (HANDLE)_beginthreadex(NULL, 0, threadFunC, NULL, 0, NULL);//等待子線程結束WaitForSingleObject(hth1, INFINITE);WaitForSingleObject(hth2, INFINITE);WaitForSingleObject(hth3, INFINITE);//一定要記得關閉線程句柄CloseHandle(hth1);CloseHandle(hth2);CloseHandle(hth3);//刪除臨界區DeleteCriticalSection(&g_cs1);DeleteCriticalSection(&g_cs2);DeleteCriticalSection(&g_cs3); }?
為什么會這樣呢,因為臨界區有所有權的概念,即某個線程進入臨界區后,就擁有該臨界區的所有權,在他離開臨界區之前,他可以無限次的再次進入該臨界區,上例中線程A獲得臨界區1的所有權后,在線程C調用LeaveCriticalSection(&g_cs1)之前,A是可以無限次的進入臨界區1的。利用信號量之所以可以實現題目的要求,是因為信號量沒有所有權的概念,某個線程獲得信號量后,如果信號量的值為0,那么他一定要等到信號量被釋放時,才能再次獲得
關于臨界區的詳細解釋清參考秒殺多線程第五篇 經典線程同步 關鍵段CS
?
【版權聲明】轉載請注明出處:http://www.cnblogs.com/TenosDoIt/p/3601308.html
轉載于:https://www.cnblogs.com/TenosDoIt/p/3601308.html
總結
以上是生活随笔為你收集整理的windows多线程同步--临界区的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios 学习常用网站
- 下一篇: IOS开发之----异常处理