多線程編程之臨界區的應用

一 臨界區特點
臨界區(Critical Section)是一段供線程獨佔式訪問的代碼,也就是說若有一線程正在訪問該代碼段,其它線程想要訪問,只能等待當前線程離開該代碼段方可進入,這樣保證了線程安全。他工作於用戶級(相對於內核級),在Window系統中CRITICAL_SECTION實現臨界區相關機制。

二 臨界區相關函數:

void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection)  // 初始化臨界區

void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection)       // 進入臨界區

void LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection)       // 離開臨界區

void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection)      // 釋放臨界區資源

使用示例:

[cpp] view plain copy
  1. #include <windows.h>  
  2.    
  3. static CRITICAL_SECTION cs; // 定義臨界區對象,如果程序是OOP的,可以定義爲類non-static成員  
  4.   
  5. // 在進入多線程環境之前,初始化臨界區  
  6. InitializeCriticalSection(&cs);  
  7.    
  8. void f()  
  9. {      
  10.     EnterCriticalSection(&cs);// 進入臨界區,其它線程則無法進入  
  11.    
  12.     // 安全訪問該區域  
  13.    
  14.       
  15.     LeaveCriticalSection(&cs);  // 離開臨界區,其它線程可以進入  
  16. }  
  17.    
  18. // 釋放臨界區資源,當不再使用臨界區時調用該函數  
  19. DeleteCriticalSection(&cs);  
三 臨界區的應用
EnterCriticalSection和LeaveCriticalSection跟new/delete一樣是成對調用的,很多時候在調用EnterCriticalSection以後不得不在多處加入LeaveCriticalSection,因爲臨界區內有return,break,continue,goto等等跳轉,一不小心就會造成死鎖。基於這個原因,在很多開源代碼中都對CRITICAL_SECTION進行了封裝。下面是我從某開源庫中摘取的封裝後的代碼:
[cpp] view plain copy
  1. #include <Windows.h>  
  2.   
  3. class Mutex {  
  4. public:  
  5.   Mutex()                      { InitializeCriticalSection(§ion); }  
  6.   ~Mutex()                     { DeleteCriticalSection(§ion); }  
  7.   void  Enter()                { EnterCriticalSection(§ion); }  
  8.   void  Leave()                { LeaveCriticalSection(§ion); }  
  9.   
  10.   struct Lock;  
  11. protected:  
  12.   Mutex(const Mutex&);  
  13.   Mutex& operator=(const Mutex&);  
  14.   
  15.   CRITICAL_SECTION section;  
  16. };  
  17.   
  18. struct Mutex::Lock {  
  19.   Mutex& s;  
  20.   Lock(Mutex& s) : s(s) { s.Enter(); }  
  21.   ~Lock()               { s.Leave(); }  
  22. };  
上面Mutex封裝了CRITICAL_SECTION相關的四個函數,Mutex的對象可作爲類的non-static成員,這樣通過Mutex的構造和析構執行InitializeCriticalSection和DeleteCriticalSection。
在進入臨界區的地方(函數體內)定義Mutex::Lock的對象作爲局部變量,通過Mutex::Lock對象的生命週期控制臨界區範圍。

使用示例:

[cpp] view plain copy
  1. class A{  
  2. public:  
  3.   void Foo();  
  4. private:  
  5.   Mutex mutex;  
  6. };  
  7.   
  8. void A::Foo()  
  9. {    
  10.   Mutex::Lock lock(mutex);  
  11.   // 臨界區代碼  
  12. }  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章