您好,登錄后才能下訂單哦!
臨界區(qū)(Crtical Section)同步對(duì)象
用戶模式下的同步對(duì)象
Win32中,最容易使用的一個(gè)同步機(jī)制就是(關(guān)鍵段)Critical Section, 某些共享資源具有互斥性,也就是它要求被互斥地使用,他也是用于資源的互斥, 在大部分情況下,使用臨界區(qū)替換Mutex(Mutex是內(nèi)核模式下的同步對(duì)象)。
局限性:他只能用于同步單個(gè)進(jìn)程中的線程。
在任何同步機(jī)制當(dāng)中,無論是哪個(gè)操作系統(tǒng)下,都不要
長時(shí)間的鎖住資源,如果一直鎖定資源,就會(huì)一致阻止其他線程的執(zhí)行,
使整個(gè)程序,處于完全停止的狀態(tài)。
不要在critical section中調(diào)用Sleep或任何Wait等待之類的api函數(shù).
、、、 臨界區(qū)很容器造成資源死鎖.
相關(guān)Api函數(shù)
1初始化一個(gè)臨界區(qū)
InitializeCriticalSection函數(shù)
VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection //critical section);
lpCriticalSection 臨界資源對(duì)象指針
2釋放一個(gè)臨界區(qū)對(duì)象來釋放所有的資源,使得不再擁有這個(gè)對(duì)象
void DeleteCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
)
lpCriticalSection 指向一個(gè)不再需要的CRITICAL_SECTION變量
3 進(jìn)入臨界區(qū),也就意味著我進(jìn)行加鎖,在他之后已經(jīng)加鎖了
void EnterCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
)
lpCriticalSection 臨界區(qū)資源對(duì)象指針
4 離開臨界區(qū) ,也就意味著解鎖,所有的資源都處于安全狀態(tài)
void LeaveCriticalSection(
LPCRITICAL_SECTION lpCriticalSection
)
lpCriticalSection 臨界區(qū)資源對(duì)象指針
臨界區(qū)和Mutex的區(qū)別
臨界區(qū)是用戶模式下的,優(yōu)點(diǎn)是速度快,缺點(diǎn)是容易線程死鎖。他
不能跨進(jìn)程,而Mutex內(nèi)核模式下的同步對(duì)象是可以進(jìn)行,安全的跨進(jìn)程操作,但是他相對(duì)與用戶模式,速度比較慢, 因此正常情況下,使用
臨界區(qū)。
臨界區(qū) Mutex
1 速度: 快 慢
2 跨進(jìn)程: 不可以 可以
3 聲明: CRITICAL_SECTION cs HANDLE hmtx;
4 初始化: InitializeCriticalSection(&cs) hmtx = CreateMutex(NULL,FALSE,NULL);
5 清理: CloseHandle DeleteCriticalSection
6 無限的等待:EnterCriticalSection(&cs) WaitForSingleObject(,INFINITE).
7 不等待(不阻塞)TryEnterCriticalSection(&cs) WaitForSingleObject(,0);
8 任意時(shí)間 臨界區(qū)是沒有這個(gè)功能 WaitForSingleObject(,1000)
9 釋放(解鎖)LeaveCriticalSection(&cs)
ReleaseMutex(.);
臨界區(qū)使用實(shí)例
首先定義一個(gè)全局的CRITICAL_SECTION g_cs;
在Create里初始化臨界區(qū)
case WM_CREATE: { int cyChar = HIWORD(GetDialogBaseUnits()); thrParams2.hwnd = hWnd; thrParams2.cyChar = cyChar; //初始化臨界區(qū) InitializeCriticalSection(&g_cs); //創(chuàng)建線程 HANDLE handleTicket1 = CreateThread(NULL, 0, ThrCalcProc1, &thrParams2, 0, NULL); HANDLE handleTicket2 = CreateThread(NULL, 0, ThrCalcPro2, &thrParams2, 0, NULL); //關(guān)閉線程句柄 CloseHandle(handleTicket1); CloseHandle(handleTicket2); } case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意繪圖代碼... TextOut(hdc, clientCX / 4, 0, _T("使用臨界區(qū)實(shí)現(xiàn)同步"), lstrlen(_T("使用臨界區(qū)實(shí)現(xiàn)同步"))); EndPaint(hWnd, &ps); break; case WM_DESTROY: //清理臨界區(qū)的指針內(nèi)存 DeleteCriticalSection(&g_cs); PostQuitMessage(0); break;
然后觀察線程的回調(diào)函數(shù)
DWORD WINAPI ThrCalcProc1(LPVOID lp) { //獲得結(jié)構(gòu)體指針 PPARAMS param2 = static_cast<PPARAMS>(lp); //生成隨機(jī)數(shù)種子 srand(time(NULL)); TCHAR szBuf[50] = { 0 }; HDC hdc; while (true) { //休眠一秒 不要在進(jìn)入臨界區(qū) 休眠 Sleep(1000); //進(jìn)入臨界區(qū) (加鎖) EnterCriticalSection(&g_cs); //g_subjectNum是數(shù)字題的數(shù)量 if (g_subjectNum > 0) { //檢查文本是否超出窗口顯示范圍,如果是就刷新窗口,并重新設(shè)置iLine值 //g_iLine2 = CheckTextRange(param2->hwnd, param2->cyChar, param2->cyChar,g_iLine2); //隨機(jī)產(chǎn)生兩個(gè)數(shù) int lval = rand() % 100; int rval = rand() % 100; int res = lval + rval; //把解鎖 繪制到窗口上 wsprintf(szBuf, _T("線程1第%d題:%d + %d = %d"),g_subjectNum--,lval,rval,res); hdc = GetDC(param2->hwnd); TextOut(hdc, 0, g_iLine2*param2->cyChar, szBuf, lstrlen(szBuf)); ReleaseDC(param2->hwnd,hdc); g_iLine2++; //解鎖 LeaveCriticalSection(&g_cs); } else { //解鎖 LeaveCriticalSection(&g_cs); break; } } return 0; }
代碼下載地址:http://down.51cto.com/data/2329647
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。