通用元件‎ > ‎

關鍵區域

關鍵區域(critical section)是多執行緒環境下的一種保護機制,藉由關鍵區域可以保證在資料的使用或修改期間內,不會有其他的執行緒修改或使用。
 
void F1() 
{
  static CriticalSec csObject;
  CriticalSecHandle AutoCSH(csObject);
  ... 其他程式碼 ....
}

void F2() 
{
  static CriticalSec csObject;
  csObject.Enter();
  ... 其他程式碼 .... 
  csObject.Leave();
} 

F2 較有效率,F1 較安全,因 Enter() 和 Leave() 必須成對使用,F1 可避免被遺漏了,對無回傳值的函數以上兩個用法都行,但對有回傳值的函數只有以下的選擇:

int F3() 
{
  static CriticalSec csObject;
  CriticalSecHandle AutoCSH(csObject);
  ... 其他程式碼 ....
  return Obj.Value();
}

只有 F3 的用法才能保證直到回傳結束,資料都沒被篡改過。

 

範例一

#include <CRITICAL.HPP>
using namespace CxxlMan; class A
{
CriticalSec csObject;
int m_i,m_j;
public:
A()
{ m_i = 0;
m_j = 0;
} void put(int i,int j)
{
csObject.Enter();
m_i = i;
m_j = j; csObject.Leave(); } int get()
{ CriticalSecHandle AutoCSH(csObject);
return m_i + m_j;
} };

 
 

死鎖

CriticalSec 所採用的是 獨佔與等待 的處理方式,當一個執行緒已佔用一個 CriticalSec 的情況下再要求另一個 CriticalSec 時,有可能發生死鎖(dead lock)的情況,除非你確定不會死鎖,否則不應連續要求兩個以上的 CriticalSec,以下是一個避免死鎖的例子:

#include <CRITICAL.HPP> 
using namespace CxxlMan;

class A;
class B;
class A
{
  CriticalSec csObject;
  int m_i,m_j;
public:
  A()
  {
    m_i = 0;
    m_j = 0;
  }
  void put(int i,int j)
  {
    csObject.Enter();
    m_i = i;
    m_j = j;
    csObject.Leave();
  }
  int get(B *B_Obj);
};
 
class B
{
  CriticalSec csObject;
  int m_i,m_j;
public:
  B()
  {
    m_i = 0;
    m_j = 0;
  }
  void Put(int &I,int &J)
  {
    csObject.Enter();
    m_i = I++;
    m_j = J++;
    csObject.Leave();
  }
  void Send(A *A_Obj)
  {
    // 先複製資料
    csObject.Enter();
    int I = m_i;
    int J = m_j;
    csObject.Leave();
    A_Obj->put(I,J);  // 先離開 CriticalSec 再叫用其他有 CriticalSec 保護的物件
  }
};
int A::get(B *B_Obj)
{
  // 先複製資料
  csObject.Enter();
  int I = m_i;
  int J = m_j;
  csObject.Leave();

  B_Obj->Put(I,J); // 先離開 CriticalSec 再叫用其他有 CriticalSec 保護的物件
  CriticalSecHandle AutoCSH(csObject); // 再一次進入 CriticalSec 以更新資料
  int m_i = I;
  int m_j = J;
  return m_i + m_j;
}
 
 

引入檔

CRITICAL.HPP

程式庫

cxxlcommon 

 
Comments