variable de condición: ¿por qué llamar a pthread_cond_signal () antes de llamar a pthread_cond_wait () es un error lógico?

Está escrito en el tutorial de hilos POSIX https://computing.llnl.gov/tutorials/pthreads/ que es un error lógico.

¿Mi pregunta es por qué es un error lógico?

En mi progtwig, necesito usar estas señales, sin embargo, no puedo garantizar que haya un hilo que estará en el estado _cond_wait. Traté de probarlo y no pasó nada. ¿Esto puede causar un comportamiento inesperado o algo peor?

¡gracias!

La respuesta del fuego se acerca más, pero no está del todo clara:
las variables condicionales solo deben usarse para señalar un cambio en una condición .

El hilo 1 verifica una condición. Si la condición no se cumple, él espera en la variable de condición hasta que se cumpla la condición. Debido a que la condición se verifica primero, no debería importarle si la variable de condición fue señalada:

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

El subproceso 2 cambia la condición y señala el cambio a través de la variable de condición. A él no le importa si los hilos están esperando o no:

 pthread_mutex_lock(&mutex); changeCondition(); pthread_mutex_unlock(&mutex); pthread_cond_signal(&cond) 

La conclusión es: la comunicación se realiza a través de alguna condición. Una variable de condición solo activa los hilos en espera para que puedan verificar la condición .

Ejemplos de condiciones:

  • La cola no está vacía, por lo que se puede tomar una entrada de la cola
  • Se establece un indicador booleano, por lo que el hilo espera s hasta que el otro hilo indique que está bien continuar
  • algunos bits en un conjunto de bits se establecen, por lo que el hilo de espera puede manejar los eventos correspondientes

ver también ejemplo pthread

Mis 2 centavos: no conozco los efectos secundarios de llamar a * pthread_cond_signal () * cuando no se ha bloqueado ningún hilo llamando a * pthread_cond_wait () *. Esto es realmente un detalle de implementación. Lo que creo es que, si su modelo threading / timimg no garantiza el orden correcto entre la espera y la señal, probablemente debería considerar un mecanismo de sincronización diferente [como un semáforo simple, por ejemplo] cuando puede indicar el semáforo del hilo B incluso si el hilo A no ha alcanzado el punto de sincronización. Cuando el hilo A llegue al punto de sincronización, encontrará que el semáforo se incrementó y entrará en la sesión crítica.

Una variable de condición permite que un subproceso despierte a otro desde una espera. Funcionan solo si hay un hilo esperando en el momento en que activa la condición. La forma de garantizar que este sea el caso es que el hilo de espera bloquee un mutex que esté vinculado a la condición y que el hilo de señalización bloquee ese mutex antes de activar la condición. En otras palabras, el hilo de señalización solo puede bloquear el mutex y activar la condición si el otro hilo tenía el mutex bloqueado pero ahora está esperando.

Estoy más familiarizado con el impulso, así que lo usaré en este ejemplo:

 // A shared mutex, global in this case. boost::mutex myMutex; // Condition variable boost::condition_variable myCondition; void threadProc() { // Lock the mutex while the thread is running. boost::mutex::scoped_lock guard( myMutex ); while( true ) { // Do stuff, then... myCondition.wait( guard ); // Unlocks the mutex and waits for a notification. } } void func() { // Function wants to trigger the other thread. Locks the mutex... boost::mutex::scoped_lock guard( myMutex ); // Since the mutex is locked, we know that the other thread is // waiting on the condition variable... myCondition.notify_all(); } 

Señalar una variable de condición cuando no hay espera correspondiente es un error lógico porque nada recibirá la señal. Las variables de condición no permanecen en estado señalizado.

Si no le importa que esta señal se pierda, no hay ningún error. Solo se trata de un error si espera que el hilo que está esperando en espera se despierte inmediatamente después de cond_wait ().

Como este es el caso de uso habitual para pthread_cond, el tutorial llama a este error lógico. Pero nada se bloqueará y no se producirá ningún comportamiento inesperado. En ejecución normal, el flujo cond_signal () aún puede emitirse cuando no hay subprocesos en cond_wait (): fe, todos los lectores pueden estar simplemente procesando mensajes cuando el escritor agrega otra pieza de datos en la cola.