除了臨界區(qū)對象進能夠被用于一個進程內(nèi)的線程使用外,臨界區(qū)對象同于其他互斥體對象一樣,也可以提供同步機制.事件,互斥體和信號量對象也能夠被用于單個進程實現(xiàn)資源互斥訪問,與此相比,為了實現(xiàn)同步互斥訪問共享資源,臨界區(qū)對象提供一種更加輕巧,快速和有效的機制.象互斥體對象一樣,臨界區(qū)對象也可以被一個使用它來阻止同步訪問共享資源的線程所用于.例如:一個進程隨時可以使用一個臨界區(qū)對象來阻止其他線程修改一個局數(shù)據(jù)結(jié)構(gòu). 進程負責(zé)為一個臨界區(qū)分配內(nèi)存.典型地,就是宣布一個CRITICAL_SECTION類型的變量.線程在使用它之前,臨界區(qū)對象必須使用InitializeCriticalSection函數(shù)進行初始化.線程使用EnterCriticalSection或TryEnterCriticalSection函數(shù)獲取臨界區(qū)所有權(quán),并通過LeaveCriticalSection函數(shù)釋放臨界區(qū)所用權(quán).如果當前臨界區(qū)對象被其他線程所擁有,EnterCriticalSection將無限等待為了臨界區(qū)所有權(quán).相比之下,一個互斥體對象為了互斥,等待函數(shù)會有一個指定的時間段.TryEnterCriticalSection函數(shù)無阻塞正在調(diào)用的線程而進入臨界區(qū). 一旦線程擁有臨界區(qū),它必須額外的調(diào)用EnterCriticalSection或無阻塞他的執(zhí)行的TryEnterCriticalSection函數(shù).這樣以來,當?shù)却粋€已存在的臨界區(qū)的擁有權(quán)時,就不會出現(xiàn)死鎖自己.每當它進入臨界區(qū)時,就必須調(diào)用LeaveCriticalSection來釋放對臨界區(qū)的擁有權(quán). 當臨界區(qū)被初始化之后,進程內(nèi)的任一個線程都可以調(diào)用DeleteCriticalSection函數(shù)來釋放被分配了的系統(tǒng)資源.DeleteCriticalSection函數(shù)被調(diào)用之后,這個臨界區(qū)對象就不能夠再被擁有為了同步機制了. 一旦一個臨界區(qū)對象被特有化之后,通過調(diào)用EnterCriticalSection函數(shù)而關(guān)聯(lián)度其它的線程將等待為了它的擁有權(quán).沒有等到擁有權(quán)的線程釋 放去繼續(xù)運行. 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 初始化一個臨界區(qū)對象,而臨界區(qū)對象(數(shù)據(jù)成員)由系統(tǒng)自動維護. VOID InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object ); (2) DeleteCriticalSection 釋放一個沒有被占有的臨界區(qū)對象的所有資源. VOID DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object ); (3) EnterCriticalSection 用來等待臨界區(qū)對象的所有權(quán),當調(diào)用線程賦予所有權(quán),本函數(shù)返回,如果沒能等待到,那么導(dǎo)致線程暫停. VOID EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object ); (4) LeaveCriticalSection 釋放指定臨界區(qū)對象所有權(quán) void LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection //pointer to critical section object ); 例子: CRITICAL_SECTION g_cs; //臨界區(qū)對象 void main() { HANDLE thread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL); HANDLE thread2 = CreateThread(NULL, 0, Fun2Proc, NULL, 0, NULL); CloseHandle(thread1); CloseHandle(thread2); //初始化一個臨界區(qū)對象 InitializeCriticalSection(&g_cs); Sleep(4000); //釋放一個沒有被占有的臨界區(qū)對象的所有資源 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; } //以下是我自己編寫實現(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); } };
|