Non è possibile che due (o più) thread acquisiscano il blocco contemporaneamente. Esistono alcuni tipi di metodi di sincronizzazione per esempio:
Attesa attiva - blocco spin
pseudocodice:
1. while ( xchg(lock, 1) == 1); - entry protocole
XCHG è un esempio di operazione atomica (esiste sull'architettura x86) che prima imposta un nuovo valore per una variabile "lock" e quindi restituisce il vecchio valore. Atomic significa che non può essere interrotto, nell'esempio sopra riportato tra l'impostazione di un nuovo valore e il ritorno di vecchio. Atomico - risultato deterministico, non importa quale.
2. Your code
3. lock = 0; - exit protocol
Quando il blocco è uguale a 0, un altro thread può accedere alla sezione critica, mentre il loop termina.
Sospensione del thread, ad esempio conteggio del semaforo
Esistono due operazione atomica .Wait()
ed .Signal()
e abbiamo variabile intera consente di chiamare int currentValue
.
Wait():
if (currentValue > 0) currentValue -= 1;
else suspend current thread;
Signal():
If there exists thread suspended by semaphore wake up one of them
Else currentValue += 1;
Ora risolvere il problema della sezione critica è davvero semplice:
pseudocodice:
mySemaphore.Wait();
do some operations - critical section
mySemaphore.Signal();
Di solito l'API del thread di programmazione dovrebbe darti la possibilità di specificare i thread simultanei massimi nella sezione critica dei semafori. Ovviamente ci sono più tipi di sincronizzazione nei sistemi multithread (mutex, monitor, semaforo binario ecc.) Ma si basano su idee sopra. Si potrebbe sostenere che i metodi che usano la sospensione dei thread dovrebbero essere preferiti all'attesa attiva (quindi la CPU non è sprecata) - non è sempre la verità. Quando il thread viene sospeso, ha luogo un'operazione costosa chiamata switch di contesto. Tuttavia è ragionevole quando il tempo di attesa è breve (numero di thread ~ numero di core).