MFC線程(二):線程同步臨界區CRITICAL SECTION

來源:互聯網
上載者:User

當多個線程同時使用相同的資源時,由於是並發執行,不能保證先後順序.所以假如時一個公開變數被幾個線程同時使用會造成該變數值的混亂.

下面來舉個簡單例子.

假如有一個字元陣列變數

char g_charArray[4];

CString szResult;

AfxBeginThread(FunOne,NULL);  //FunOne給數組賦值全為S

AfxBeginThread(FunTwo,NULL); //FunTwo也給數組賦值全為B

AfxBeginThread(GetResult,NULL);   //得到數組的值,本來期望的值為最後一次賦的值BBBB.但實際結果是不確定的,可能是SBSB,SSBB或者其它

 

UINT FunOne(LPVOID pParam){ //給數組賦值

for(int i =0; i < 4; i++){

g_charArray[i] = 'S';

Sleep(10);

}

return 0;

}

UINT FunTwo(LPVOID pParam){//得到數組值

for(int i =0; i < 4; i++){

g_charArray[i] = 'B';

Sleep(10);

}

return 0;

}

 

UINT GetResult(LPVOID pParam){//給數組賦值

szResult = CString(g_charArray);

return 0;

}

 

Win32 API中臨界區(Critical Section)

為了使公開變數不會被毫無秩序,混亂的更改.我們希望一個線程使用這個變數時其他線程就不能使用,只能等別的線程用完了才用.

於是出現了臨界區這說法,相當於把使用到的變數的記憶體看作一塊地區,當某個線程使用時就進入該地區,使用完了離開.當有一個線程進入該地區時其他線程就只能在外面等.臨界區的使用如下.

臨界區只能用於同一個進程內的線程同步.如果想要多個進程間的線程同步就不能用它了.

 

CRITICAL_SECTION g_criSection //定義臨界區變數

 

void MainTestFun{

InitializeCriticalSection(&g_criSection);  //使用前必須初始化

char g_charArray[4];

CString szResult;

AfxBeginThread(FunOne,NULL);

AfxBeginThread(FunTwo,NULL);

AfxBeginThread(GetResult,);  //此時得到的值總是BBBB或者SSSS,哪一個線程擁有臨界區不確定.只能保證某一個時間只能有一個線程擁有

//DeleteCriticalSection(&g_criSection); 使用完了臨界區就要刪除掉,但是在這裡這樣使用可能會出錯.因為必須保證在刪除時這個臨界區沒有再被使用了.所以如果一個類中,一般把它放解構函式中去調用.

}

 

 

//線上程調用的函數的開始調用EnterCriticalSection結束時調用CriticalSection(&g_criSection);

//在中間有用到的所有資源在被使用時其他線程不能使用(不能讀也不能改寫).其它兩個函數FunOne,GetResult按同樣的方法添加這兩行代碼.這裡不再寫出來了.

UINT FunOne(LPVOID pParam){

EnterCriticalSection(&g_criSection); //表示進入臨界區

for(int i =0; i < 4; i++){

g_charArray[i] = 'S';

Sleep(1);

}

LeaveCriticalSection(&g_criSection); //離開臨界區

return 0;

}

 

MFC中的臨界區類

MFC把上面的操作封裝成一個類CCriticalSection,使用函數Lock與Unlock表示進入和離開臨界區.上鎖和解鎖的說法是更符合我們的習慣思維的.

#include "afxmt.h" //需要添加該標頭檔引用

CCriticalSection g_criSection;

void MainTestFun{

char g_charArray[4];

CString szResult;

AfxBeginThread(FunOne,NULL);

AfxBeginThread(FunTwo,NULL);

AfxBeginThread(GetResult,); //此時得到的值總是BBBB或者SSSS,哪一個線程擁有臨界區不確定.只能保證某一個時間只能有一個線程擁有 }

 

//其它兩個類也同樣加上這兩行代碼

UINT FunOne(LPVOID pParam){

g_criSection.Lock()//給所有使用的資源上鎖

for(int i =0; i < 4; i++){

g_charArray[i] = 'S';

Sleep(1);

}

g_criSection.UnLock(); //給使用的資源解鎖

return 0;

}

 

 

其他線程同步的方法

使線程同步共有4種方法:

1.臨界區(critical section)

2.事件(event)

3.訊號量(Semaphore)

4.互拆量(Mutex)

 

其中1臨界區是使用者物件,所以沒太多許可權,只能處理同一個進程內的線程同步

而剩下的2,3,4都是核心對象,許可權比較大,可以跨進程使用,因此能夠處理不同進程間的線程同步問題.

其中的Mutext和臨界區適用的情境基本上一樣,只不過Mutext是核心對象,而critical section是使用者物件

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.