|
除了臨界區(qū)對(duì)象進(jìn)能夠被用于一個(gè)進(jìn)程內(nèi)的線程使用外,臨界區(qū)對(duì)象同于其他互斥體對(duì)象一樣,也可以提供同步機(jī)制.事件,互斥體和信號(hào)量對(duì)象也能夠被用于單個(gè)進(jìn)程實(shí)現(xiàn)資源互斥訪問,與此相比,為了實(shí)現(xiàn)同步互斥訪問共享資源,臨界區(qū)對(duì)象提供一種更加輕巧,快速和有效的機(jī)制.象互斥體對(duì)象一樣,臨界區(qū)對(duì)象也可以被一個(gè)使用它來阻止同步訪問共享資源的線程所用于.例如:一個(gè)進(jìn)程隨時(shí)可以使用一個(gè)臨界區(qū)對(duì)象來阻止其他線程修改一個(gè)局?jǐn)?shù)據(jù)結(jié)構(gòu). 進(jìn)程負(fù)責(zé)為一個(gè)臨界區(qū)分配內(nèi)存.典型地,就是宣布一個(gè)CRITICAL_SECTION類型的變量.線程在使用它之前,臨界區(qū)對(duì)象必須使用InitializeCriticalSection函數(shù)進(jìn)行初始化.線程使用EnterCriticalSection或TryEnterCriticalSection函數(shù)獲取臨界區(qū)所有權(quán),并通過LeaveCriticalSection函數(shù)釋放臨界區(qū)所用權(quán).如果當(dāng)前臨界區(qū)對(duì)象被其他線程所擁有,EnterCriticalSection將無限等待為了臨界區(qū)所有權(quán).相比之下,一個(gè)互斥體對(duì)象為了互斥,等待函數(shù)會(huì)有一個(gè)指定的時(shí)間段.TryEnterCriticalSection函數(shù)無阻塞正在調(diào)用的線程而進(jìn)入臨界區(qū). 一旦線程擁有臨界區(qū),它必須額外的調(diào)用EnterCriticalSection或無阻塞他的執(zhí)行的TryEnterCriticalSection函數(shù).這樣以來,當(dāng)?shù)却粋€(gè)已存在的臨界區(qū)的擁有權(quán)時(shí),就不會(huì)出現(xiàn)死鎖自己.每當(dāng)它進(jìn)入臨界區(qū)時(shí),就必須調(diào)用LeaveCriticalSection來釋放對(duì)臨界區(qū)的擁有權(quán). 當(dāng)臨界區(qū)被初始化之后,進(jìn)程內(nèi)的任一個(gè)線程都可以調(diào)用DeleteCriticalSection函數(shù)來釋放被分配了的系統(tǒng)資源.DeleteCriticalSection函數(shù)被調(diào)用之后,這個(gè)臨界區(qū)對(duì)象就不能夠再被擁有為了同步機(jī)制了. 一旦一個(gè)臨界區(qū)對(duì)象被特有化之后,通過調(diào)用EnterCriticalSection函數(shù)而關(guān)聯(lián)度其它的線程將等待為了它的擁有權(quán).沒有等到擁有權(quán)的線程釋 放去繼續(xù)運(yùn)行. SECTICAL_SECTION結(jié)構(gòu): typedef struct _RTL_CRITICAL_SECTION { PRTL_CRITICAL_SECTION_DEBUG DebugInfo; // // The following three fields control entering and exiting the critical // section for the resource // LONG LockCount; LONG RecursionCount; HANDLE OwningThread; // from the thread's ClientId->UniqueThread HANDLE LockSemaphore; ULONG_PTR SpinCount; // force size on 64-bit systems when packed } RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION; typedef RTL_CRITICAL_SECTION CRITICAL_SECTION; typedef PRTL_CRITICAL_SECTION PCRITICAL_SECTION; typedef PRTL_CRITICAL_SECTION LPCRITICAL_SECTION; 操作臨界區(qū)的相關(guān)函數(shù) (1) InitializeCriticalSection 初始化一個(gè)臨界區(qū)對(duì)象,而臨界區(qū)對(duì)象(數(shù)據(jù)成員)由系統(tǒng)自動(dòng)維護(hù). VOID InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object ); (2) DeleteCriticalSection 釋放一個(gè)沒有被占有的臨界區(qū)對(duì)象的所有資源. VOID DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object ); (3) EnterCriticalSection 用來等待臨界區(qū)對(duì)象的所有權(quán),當(dāng)調(diào)用線程賦予所有權(quán),本函數(shù)返回,如果沒能等待到,那么導(dǎo)致線程暫停. VOID EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object ); (4) LeaveCriticalSection 釋放指定臨界區(qū)對(duì)象所有權(quán) void LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object ); 例子: CRITICAL_SECTION g_cs; //臨界區(qū)對(duì)象 void main() { HANDLE thread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL); HANDLE thread2 = CreateThread(NULL, 0, Fun2Proc, NULL, 0, NULL); CloseHandle(thread1); CloseHandle(thread2); //初始化一個(gè)臨界區(qū)對(duì)象 InitializeCriticalSection(&g_cs); Sleep(4000); //釋放一個(gè)沒有被占有的臨界區(qū)對(duì)象的所有資源 DeleteCriticalSection(&g_cs); } DWORD WINAPI Fun1Proc(LPVOID lpParam) { while(TRUE) { EnterCriticalSection(&g_cs); if (ticket>0) { cout<<"thread1 sells: "<<ticket--<<endl; Sleep(1); } else break; LeaveCriticalSection(&g_cs); } return 0; } DWORD WINAPI Fun1Proc(LPVOID lpParam) { while(TRUE) { EnterCriticalSection(&g_cs); if (ticket>0) { cout<<"thread2 sells: "<<ticket--<<endl; Sleep(1); } else break; LeaveCriticalSection(&g_cs); } return 0; } //以下是我自己編寫實(shí)現(xiàn)臨界區(qū)的類: //頭文件 CriticalSection.h #pragma once class CCriticalSection { private: CRITICAL_SECTION m_CS; public: CCriticalSection() { ::InitializeCriticalSection(&m_CS); } ~CCriticalSection() { ::DeleteCriticalSection(&m_CS); } operator LPCRITICAL_SECTION() { return &m_CS; } void Lock() { ::EnterCriticalSection(&m_CS); } void UnLock() { ::LeaveCriticalSection(&m_CS); } };
|