通俗解釋就像上廁所:
門鎖了,就等著,等到別人出來了,進去鎖上,然後該幹什麼幹什麼,幹完了,把門開啟
門沒鎖,就進去,鎖上,然後該幹什麼幹什麼,幹完了,把門開啟
--------------------------------------------------
多線程中用來確保同一時刻只有一個線程操作被保護的資料
InitializeCriticalSection(&cs);//初始化臨界區
EnterCriticalSection(&cs);//進入臨界區
//操作資料
MyMoney*=10;//所有訪問MyMoney變數的程式都需要這樣寫Enter.. Leave...
LeaveCriticalSection(&cs);//離開臨界區
DeleteCriticalSection(&cs);//刪除臨界區
多個線程操作相同的資料時,一般是需要按順序訪問的,否則會引導資料錯亂,無法控制資料,變成隨機變數。為解決這個問題,就需要引入互斥變數,讓每個線程都按順序地訪問變數。這樣就需要使用EnterCriticalSection和LeaveCriticalSection函數。
比如說我們定義了一個共用資源dwTime[100],兩個線程ThreadFuncA和ThreadFuncB都對它進行讀寫操作。當我們想要保證 dwTime[100]的操作完整性,即不希望寫到一半的資料被另一個線程讀取,那麼用CRITICAL_SECTION來進行線程同步如下:
第一個線程函數:
DWORD WINAPI ThreadFuncA(LPVOID lp)
{
EnterCriticalSection(&cs);
...
// 操作dwTime
...
LeaveCriticalSection(&cs);
return 0;
}
寫出這個函數之後,很多初學者都會錯誤地以為,此時cs對dwTime進行了鎖定操作,dwTime處於cs的保護之中。一個“自然而然”的想法就是——cs和dwTime一一對應上了。
這麼想,就大錯特錯了。dwTime並沒有和任何東西對應,它仍然是任何其它線程都可以訪問的。如果你像如下的方式來寫第二個線程,那麼就會有問題:
DWORD WINAPI ThreadFuncB(LPVOID lp)
{
...
// 操作dwTime
...
return 0;
}
當線程ThreadFuncA執行了EnterCriticalSection(&cs),並開始操作dwTime[100]的時候,線程 ThreadFuncB可能隨時醒過來,也開始操作dwTime[100],這樣,dwTime[100]中的資料就被破壞了。
為了讓CRITICAL_SECTION發揮作用,我們必須在訪問dwTime的任何一個地方都加上 EnterCriticalSection(&cs)和LeaveCriticalSection(&cs)語句。所以,必須按照下面的 方式來寫第二個線程函數:
DWORD WINAPI ThreadFuncB(LPVOID lp)
{
EnterCriticalSection(&cs);
...
// 操作dwTime
...
LeaveCriticalSection(&cs);
return 0;
}
這樣,當線程ThreadFuncB醒過來時,它遇到的第一個語句是EnterCriticalSection(&cs),這個語句將對cs變數 進行訪問。如果這個時候第一個線程仍然在操作dwTime[100],cs變數中包含的值將告訴第二個線程,已有其它線程佔用了cs。因此,第二個線程的 EnterCriticalSection(&cs)語句將不會返回,而處於掛起等待狀態。直到第一個線程執行了 LeaveCriticalSection(&cs),第二個線程的EnterCriticalSection(&cs)語句才會返回, 並且繼續執行下面的操作。
這個過程實際上是通過限制有且只有一個函數進入CriticalSection變數來實現程式碼片段同步的。簡單地說,對於同一個 CRITICAL_SECTION,當一個線程執行了EnterCriticalSection而沒有執行LeaveCriticalSection的時 候,其它任何一個線程都無法完全執行EnterCriticalSection而不得不處於等待狀態。
再次強調一次,沒有任何資源被“鎖定”,CRITICAL_SECTION這個東東不是針對於資源的,而是針對於不同線程間的程式碼片段的!我們能夠用它來進 行所謂資源的“鎖定”,其實是因為我們在任何訪問共用資源的地方都加入了EnterCriticalSection和 LeaveCriticalSection語句,使得同一時間只能夠有一個線程的程式碼片段訪問到該共用資源而已(其它想訪問該資源的程式碼片段不得不等待)。
這就是使用一個CRITICAL_SECTION時的情況。你應該要知道,它並沒有什麼可以同步的資源的“集合”。這個概念不正確。
如果是兩個CRITICAL_SECTION,就以此類推。