pthread_cond_wait pthread_cond_t c++ pthreads mutex signals condition-variable

c++ - pthread_cond_wait - pthread_cond_t



Llamar a pthread_cond_signal sin bloquear mutex (3)

Leí en alguna parte que deberíamos bloquear el mutex antes de llamar a pthread_cond_signal y desbloquear el texto alternativo después de llamarlo:

La rutina pthread_cond_signal () se usa para señalar (o reactivar) otro subproceso que está esperando la variable de condición. Se debe invocar después de bloquear mutex y debe desbloquear mutex para que se complete la rutina pthread_cond_wait ().

Mi pregunta es: ¿no está bien llamar a los métodos pthread_cond_signal o pthread_cond_broadcast sin bloquear el mutex?


De acuerdo con este manual:

Las funciones pthread_cond_broadcast() o pthread_cond_signal() pueden ser llamadas por un hilo, ya sea que posea o no el mutex que los hilos llamados pthread_cond_wait() o pthread_cond_timedwait() han asociado con la variable de condición durante sus esperas; sin embargo, si se requiere un comportamiento de programación predecible, ese subtexto será bloqueado por el hilo que llama a pthread_cond_broadcast() o pthread_cond_signal() .

Dave Butenhof (autor de Programming with POSIX Threads ) en comp.programming.threads explicó el significado de la declaración de comportamiento de programación predecible y está disponible here .


Si no bloquea el mutex en la ruta de código que cambia la condición y las señales, puede perder los despertadores. 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 esta posible intercalación de instrucciones, donde la 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);

La condition ahora es TRUE , pero el Proceso A está atascado esperando 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 despertador nunca se perderá.

(Tenga en cuenta que en realidad puede mover la pthread_cond_signal() después de pthread_mutex_unlock() , pero esto puede dar como resultado una programación menos óptima de los hilos, y ya ha bloqueado necesariamente el mutex en esta ruta de código debido a la modificación de la condición misma).


caf, en su código de muestra, el Proceso B modifica la condition sin bloquear primero el mutex. Si el Proceso B simplemente bloqueó el mutex durante esa modificación, y luego aún desbloqueó el mutex antes de llamar a pthread_cond_signal , no habría ningún problema. ¿Tengo razón al respecto?

Creo intuitivamente que la posición de caf es correcta: llamar a pthread_cond_signal sin tener el bloqueo de exclusión mutua es una mala idea. Pero el ejemplo de caf no es en realidad evidencia en apoyo de esta posición; es simplemente una evidencia en apoyo de la posición mucho más débil (prácticamente evidente) 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 llamar a pthread_cond_signal seguido de pthread_mutex_unlock produce un comportamiento correcto, pero llamar a pthread_mutex_unlock seguido de pthread_cond_signal produce un comportamiento incorrecto?