È solo il modo in cui le variabili di condizione sono (o sono state originariamente) implementate.
Il mutex viene utilizzato per proteggere la variabile condizione stessa . Ecco perché è necessario bloccarlo prima di aspettare.
L'attesa "atomicamente" sbloccherà il mutex, consentendo ad altri di accedere alla variabile di condizione (per la segnalazione). Quindi, quando la variabile condizione viene segnalata o trasmessa, uno o più thread nella lista di attesa verranno risvegliati e il mutex verrà nuovamente bloccato magicamente per quel thread.
In genere viene visualizzata la seguente operazione con variabili di condizione, illustrando come funzionano. L'esempio seguente è un thread di lavoro a cui viene dato lavoro tramite un segnale a una variabile di condizione.
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
do the work.
unlock mutex.
clean up.
exit thread.
Il lavoro viene svolto all'interno di questo ciclo, a condizione che ce ne siano alcuni disponibili quando ritorna l'attesa. Quando il thread è stato contrassegnato per smettere di funzionare (di solito da un altro thread che imposta la condizione di uscita quindi calciare la variabile di condizione per riattivare questo thread), il loop uscirà, il mutex verrà sbloccato e questo thread uscirà.
Il codice sopra è un modello per singolo consumatore poiché il mutex rimane bloccato durante il lavoro. Per una variante multi-consumatore, è possibile utilizzare, come esempio :
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
copy work to thread local storage.
unlock mutex.
do the work.
lock mutex.
unlock mutex.
clean up.
exit thread.
che consente ad altri consumatori di ricevere lavoro mentre questo fa lavoro.
La variabile condition ti alleggerisce dall'onere del polling di una condizione invece di consentire a un altro thread di avvisarti quando qualcosa deve accadere. Un altro thread può dire che il thread che funziona è disponibile come segue:
lock mutex.
flag work as available.
signal condition variable.
unlock mutex.
La stragrande maggioranza di quelli che sono spesso chiamati erroneamente risvegli spuri era generalmente sempre perché all'interno della loro pthread_cond_wait
chiamata (trasmissione) erano stati segnalati più thread , si tornava con il mutex, si faceva il lavoro, quindi si aspettava di nuovo.
Quindi il secondo thread segnalato potrebbe uscire quando non c'era lavoro da fare. Quindi dovevi avere una variabile in più che indica che il lavoro doveva essere svolto (questo era intrinsecamente protetto da mutex con la coppia condvar / mutex qui - altri thread dovevano bloccare il mutex prima di cambiarlo comunque).
E ' stato tecnicamente possibile per un filo di tornare da una condizione di attesa senza essere preso a calci da un altro processo (si tratta di una vera e propria sveglia spurio), ma, in tutti i miei molti anni a lavorare su pthreads, sia in fase di sviluppo / di servizio del codice e come utente di loro, non ho mai ricevuto una di queste. Forse era solo perché HP aveva un'implementazione decente :-)
In ogni caso, lo stesso codice che gestiva il caso errato gestiva anche autentici risvegli spuri e poiché la bandiera disponibile per il lavoro non sarebbe stata impostata per quelli.