Chiamando pthread_cond_signal senza bloccare mutex

Ho letto da qualche parte che dovremmo bloccare il mutex prima di chiamare pthread_cond_signal e sbloccare il mutext dopo averlo chiamato:

La routine pthread_cond_signal () viene utilizzata per segnalare (o ritriggersre) un altro thread che è in attesa sulla variabile condition. Dovrebbe essere chiamato dopo che il mutex è bloccato e deve sbloccare il mutex per completare la routine pthread_cond_wait ().

La mia domanda è: non è corretto chiamare i metodi pthread_cond_signal o pthread_cond_broadcast senza bloccare il mutex?

Se non si blocca il mutex nel codepath che cambia condizione e segnali, è ansible perdere i risvegli. Considera questa coppia di processi:

Processo A:

pthread_mutex_lock(&mutex); while (condition == FALSE) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); 

Processo B (errato):

 condition = TRUE; pthread_cond_signal(&cond); 

Quindi considera questo ansible interleaving delle istruzioni, dove la condition inizia come FALSE :

 Process A Process B pthread_mutex_lock(&mutex); while (condition == FALSE) condition = TRUE; pthread_cond_signal(&cond); pthread_cond_wait(&cond, &mutex); 

La condition è ora TRUE , ma il processo A è bloccato in attesa sulla variabile di condizione: ha mancato il segnale di triggerszione. Se modifichiamo il processo B per bloccare il mutex:

Processo B (corretto):

 pthread_mutex_lock(&mutex); condition = TRUE; pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); 

… quindi il precedente non può accadere; la sveglia non sarà mai mancata.

(Si noti che è ansible spostare lo stesso pthread_cond_signal() dopo pthread_mutex_unlock() , ma ciò può comportare una programmazione meno ottimale dei thread e necessariamente il blocco è già bloccato in questo percorso di codice a causa della modifica della condizione stessa).

Secondo questo manuale:

Le funzioni pthread_cond_broadcast() o pthread_cond_signal() possono essere chiamate da un thread indipendentemente dal fatto che attualmente possegga o meno il mutex che i thread che chiamano pthread_cond_wait() o pthread_cond_timedwait() hanno associato alla variabile condition durante le loro attese; tuttavia, se è richiesto un comportamento di pianificazione prevedibile, tale mutex deve essere bloccato dal thread che chiama pthread_cond_broadcast() o pthread_cond_signal() .

Il significato della dichiarazione di comportamento prevedibile per la pianificazione è stato spiegato da Dave Butenhof (autore di Programmazione con thread POSIX ) su comp.programming.threads ed è disponibile qui .

caf, nel tuo codice di esempio, Process B modifica le condition senza bloccare prima il mutex. Se Process B ha semplicemente bloccato il mutex durante quella modifica, e quindi ha ancora sbloccato il mutex prima di chiamare pthread_cond_signal , non ci sarebbero problemi — ho ragione su questo?

Credo intuitivamente che la posizione di caf sia corretta: chiamare pthread_cond_signal senza possedere il blocco mutex è una ctriggers idea. Ma l’ esempio di caf non è in realtà una prova a sostegno di questa posizione; è semplicemente una prova a sostegno della posizione molto più debole (praticamente autoevidente) che è una ctriggers idea modificare lo stato condiviso protetto da un mutex a meno che non si sia bloccato per primo quel mutex.

Qualcuno può fornire qualche codice di esempio in cui chiamare pthread_cond_signal seguito da pthread_mutex_unlock restituisce un comportamento corretto, ma chiamare pthread_mutex_unlock seguito da pthread_cond_signal produce un comportamento scorretto?