2011-08-31 134 views
12

例如,這是否有效?嵌套臨界區是否有效?

CRITICAL_SECTION cs; 

::InitializeCriticalSection(&cs); 

::EnterCriticalSection(&cs);  // First level 
::EnterCriticalSection(&cs);  // Second level 

/* do some stuff */ 

::LeaveCriticalSection(&cs);  // Second level 
::LeaveCriticalSection(&cs);  // First level 

::DeleteCriticalSection(&cs); 

很顯然,我決不會有意這樣做,但如果這個人來大約爲功能的調用效果,使得「第一等級」被稱爲鎖定對象的複雜(例如,搜索)算法和「第二級」在該對象的訪問函數中被調用?

回答

23

是的,它已經進入相同的臨界區是有效的。從the docs

後一個線程都有一個關鍵部分的所有權,它可以對EnterCriticalSection的或TryEnterCriticalSection 額外 通話無阻塞執行。這可以防止 線程在等待它已經擁有的關鍵部分時自己發生死鎖。線程每次進入關鍵部分 EnterCriticalSection和TryEnterCriticalSection成功。線程 每次進入 關鍵部分時都必須調用LeaveCriticalSection一次。

+0

+1不知道那一個! – Valmond

+0

同樣適用於所有其他類型的同步對象 - 互斥鎖,信號量等。一旦線程獲得鎖定,就可以多次重新進入鎖定而無需阻塞。只要確保釋放鎖定的次數與您輸入的次數相同,以便它可以正確釋放以供其他線程獲取。 –

+1

@Remy:不,它不適用於所有其他類型的同步對象。你當然可以擁有不可重入的互斥體。 –

9

documentation

後一個線程都有一個關鍵部分的所有權,它可以對EnterCriticalSection的或TryEnterCriticalSection額外通話無阻塞執行。這可以防止線程在等待它已經擁有的關鍵部分時發生死鎖。每次EnterCriticalSection和TryEnterCriticalSection成功時,線程都會進入臨界區。線程每次進入關鍵部分時都必須調用LeaveCriticalSection一次。

+0

擊敗你5秒:P –

+0

是的,但是......我打電話給它打了一個領帶。 – Cheeso

+0

+1對你也是如此:-) – Valmond

0

驗證其他兩個帖子。快速查看WinDbg中的Critical部分,顯示cricital節維護一個整型變量來保存遞歸計數。

0:001> dt RTL_CRITICAL_SECTION 
+0x000 DebugInfo : Ptr32 _RTL_CRITICAL_SECTION_DEBUG 
+0x004 LockCount : Int4B 
+0x008 RecursionCount : Int4B 
+0x00c OwningThread : Ptr32 Void 
+0x010 LockSemaphore : Ptr32 Void 
+0x014 SpinCount : Uint4B 

RecursionCount - 這是可能的線程獲得臨界區不止一次。該字段 指示相同線程獲取關鍵部分的次數。默認值爲 ,此字段的值爲0,表示沒有線程擁有關鍵部分。