Si no bloquea el mutex en la ruta de código que cambia la condición y las señales, puede perder las activaciones. Considere este par de procesos:
Proceso A:
pthread_mutex_lock(&mutex);
while (condition == FALSE)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
Proceso B (incorrecto):
condition = TRUE;
pthread_cond_signal(&cond);
Luego considere este posible entrelazado de instrucciones, donde condition
comienza como FALSE
:
Process A Process B
pthread_mutex_lock(&mutex);
while (condition == FALSE)
condition = TRUE;
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mutex);
El condition
es ahora TRUE
, pero el proceso A está atascado esperando en la variable de condición: perdió la señal de activación. Si modificamos el proceso B para bloquear el mutex:
Proceso B (correcto):
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
... entonces lo anterior no puede ocurrir; el despertar nunca se perderá.
(Tenga en cuenta que en realidad puede mover el pthread_cond_signal()
mismo después de pthread_mutex_unlock()
, pero esto puede resultar en una programación de subprocesos menos óptima, y necesariamente ha bloqueado el mutex ya en esta ruta de código debido al cambio de la condición en sí).
pthread_signal_cond()
se puede mover después del desbloqueo de mutex, aunque probablemente sea mejor no hacerlo. Quizás sea más correcto decir que en el punto donde está llamandopthread_signal_cond()
, ya habrá necesitado haber bloqueado el mutex para modificar la condición en sí.pthread_cond_timedwait()
lapthread_cond_wait()
operación o , se forma un enlace dinámico entre ese mutex y la variable de condición que permanece en efecto mientras en al menos un hilo está bloqueado en la variable de condición. Durante este tiempo, el efecto de un intento de cualquier hilo de esperar en esa variable de condición usando un mutex diferente no está definido " .Según este manual:
Dave Butenhof (autor de Programming with POSIX Threads ) explicó el significado de la declaración de comportamiento de programación predecible en comp.programming.threads y está disponible aquí .
fuente
caf, en su código de muestra, el Proceso B modifica
condition
sin bloquear primero el mutex. Si el Proceso B simplemente bloqueó el mutex durante esa modificación, y luego desbloqueó el mutex antes de llamarpthread_cond_signal
, no habría ningún problema, ¿tengo razón en eso?Creo intuitivamente que la posición de caf es correcta: llamar
pthread_cond_signal
sin tener el bloqueo mutex es una mala idea. Pero el ejemplo de caf no es realmente una evidencia que apoye esta posición; es simplemente evidencia en apoyo de la posición mucho más débil (prácticamente evidente por sí misma) de que es una mala idea modificar el estado compartido protegido por un mutex a menos que haya bloqueado ese mutex primero.¿Alguien puede proporcionar algún código de muestra en el que la llamada
pthread_cond_signal
seguida depthread_mutex_unlock
un comportamiento correcto, pero la llamadapthread_mutex_unlock
seguida depthread_cond_signal
un comportamiento incorrecto?fuente
pthread_cond_signal
afterpthread_mutex_unlock
puede resultar en una activación perdida porque la señal es detectada en el hilo "incorrecto", uno que se bloqueó después de ver el cambio en el predicado. Esto solo es un problema si la misma variable de condición se puede usar para más de un predicado y usted no la usapthread_cond_broadcast
, lo cual es un patrón raro y frágil de todos modos.