2011-08-31 7 views
12

Ad esempio, sarebbe valido?È valido annidare una sezione critica?

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); 

Ovviamente, non avrei mai intenzionalmente fare questo, ma se questo dovesse accadere a seguito di chiamate di funzione in modo che il "primo livello" viene chiamato a bloccare un oggetto per un complesso (ad esempio, di ricerca) l'algoritmo e il "secondo livello" viene chiamato nelle funzioni di accesso di quell'oggetto?

risposta

23

Sì, è valido inserire la stessa sezione critica già al suo interno. Da the docs:

Dopo un filo ha la proprietà di una sezione critica, può rendere ulteriori chiamate a EnterCriticalSection o TryEnterCriticalSection senza bloccare la sua esecuzione. Ciò impedisce a un thread da deadlocking in attesa di una sezione critica che già possiede . Il thread entra nella sezione critica ogni volta che EnterCriticalSection e TryEnterCriticalSection hanno esito positivo. Una discussione deve chiamare LeaveCriticalSection una volta per ogni volta che è entrato nella sezione critica .

+0

+1 Non lo sapevo! – Valmond

+0

Lo stesso vale per tutti gli altri tipi di oggetti di sincronizzazione: mutex, semafori, ecc. Una volta che un thread ha ottenuto un blocco, può rientrare nel blocco tutte le volte che lo desidera senza bloccare. Assicurati di rilasciare il blocco lo stesso numero di volte in cui lo inserisci, in modo che venga rilasciato correttamente per ottenere altri thread. –

+1

@Remy: no, non si applica a tutti gli altri tipi di oggetti di sincronizzazione. Puoi certamente avere mutex non rientranti. –

9

Dal documentation:

Dopo un filo ha la proprietà di una sezione critica, può effettuare ulteriori chiamate alle EnterCriticalSection o TryEnterCriticalSection senza bloccare la sua esecuzione. Ciò impedisce che un thread si blocchi da solo durante l'attesa di una sezione critica che già possiede. Il thread entra nella sezione critica ogni volta che EnterCriticalSection e TryEnterCriticalSection hanno esito positivo. Un thread deve chiamare LeaveCriticalSection una volta per ogni volta che è entrato nella sezione critica.

+0

Batti di 5 secondi: P –

+0

sì, ma ... beh, lo sto definendo un pareggio. – Cheeso

+0

+1 anche per te allora :-) – Valmond

0

Per convalidare gli altri due post. Un'occhiata rapida alla sezione Critical in WinDbg mostra che la sezione cricital mantiene una variabile intera per contenere i conteggi di ricorsione.

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 - È possibile che un filo di acquisire una sezione critica più di una volta. Questo campo indica quante volte lo stesso thread ha acquisito la sezione critica. Con il valore predefinito di , il valore di questo campo è 0, a indicare che non esiste un thread proprietario della sezione critica .

Problemi correlati