多线程编程之临界区的应用

一 临界区特点
临界区(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. }  

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