¿Por qué necesita un ciclo while mientras espera una variable de condición?

4 minutos de lectura

¿Por que necesita un ciclo while mientras espera una variable
MetálicoSacerdote

Di que tienes este código

pthread_mutex_lock(&cam->video_lock);
while(cam->status == WAIT_DISPLAY) // <-- Why is this a 'while' and not an 'if'?
    pthread_cond_wait(&cam->video_cond, &cam->video_lock);
pthread_mutex_unlock(&cam->video_lock);

Mi pregunta es, ¿por qué necesita un ciclo while aquí? no lo haría pthread_cond_wait solo espera hasta que el hilo de señalización señale cam_video_cond? Bien, sé que podrías tener un caso en el que cámara->estado no es igual a ESPERA_DISPAY Cuándo pthread_cond_wait se llama, pero en ese caso podría comprobarlo a través de un si condición en lugar de usar tiempo.

¿Me estoy perdiendo de algo? mi comprensión de pthread_cond_wait es que solo espera infinito si cam_video_cond no está señalizado. Además, desbloquea el cam_video_lock mutex cuando se llama, pero cuando se señala la condición, antes de regresar, se vuelve a bloquear cam_video_lock. ¿Tengo razón?

Se recomienda que todos los subprocesos verifiquen la condición después de regresar de pthread_cond_wait porque hay varias razones por las que la condición podría no ser cierta. Una de estas razones es una activación espuria; es decir, un subproceso podría despertarse aunque ningún subproceso haya señalado la condición.

Fuente : despertar espurio

Las activaciones espurias son una razón, pero las activaciones legítimas pero extrañas son otra.

Considerar:

  1. Pones un trabajo en una cola.

  2. Señala la variable de condición, activando el subproceso A.

  3. Pones un trabajo en una cola.

  4. Señala la variable de condición, activando el subproceso B.

  5. El subproceso A se programa, hace el primer trabajo.

  6. El subproceso A encuentra que la cola no está vacía y realiza el segundo trabajo.

  7. El subproceso B se programa después de haber sido activado, pero encuentra que la cola aún está vacía.

Por motivos de rendimiento, la API de POSIX permite que el sistema operativo active su subproceso incluso si la condición no se ha cumplido (eso se denomina despertar espurio).

1647538927 668 ¿Por que necesita un ciclo while mientras espera una variable
Max Popov

La razón de la necesidad de usar mientras bucle es que sólo hay dos funciones en el std::condition_variable para despertar hilos de espera:

  • notify_one() que despierta uno de los subprocesos que actualmente esperan esta condición sin posibilidad de señalar cuál despertar exactamente.
  • notify_all() que despierta todos los subprocesos que actualmente esperan esta condición.

Y porque std::condition_variable tiene solo dos funciones para despertar hilos en espera despertarás un hilo aleatorio usando notify_one() o despierta todos los subprocesos en espera usando notify_all().
Obviamente eso no es satisfactorio. y necesitamos de alguna manera señalar cuál hilo debe despertar. Y en esa situación esta semántica puede ayudar:

while (!ready) cv.wait(lck); resto parte del código

aquí, ready – el resultado del predicado que devolverá verdadero solo cuando tenga lugar la condición particular que necesita.

Cotización:

Las variables de condición se utilizan para esperar hasta que un predicado de condición en particular se vuelva verdadero. Este predicado de condición lo establece otro subproceso, generalmente el que señala la condición.

Semántica de espera de condición

Un predicado de condición debe estar protegido por un mutex. Cuando se espera una condición, la subrutina de espera (ya sea la subrutina pthread_cond_wait o pthread_cond_timedwait) desbloquea atómicamente el mutex y bloquea el subproceso. Cuando se señala la condición, el mutex se vuelve a bloquear y vuelve la subrutina de espera. Es importante tener en cuenta que cuando la subrutina regresa sin error, el predicado aún puede ser falso.

La razón es que se puede despertar más de un subproceso: ya sea un subproceso llamado subrutina pthread_cond_broadcast, o una carrera inevitable entre dos procesadores simultáneamente despertó dos subprocesos. El primer subproceso que bloquea el mutex bloqueará todos los demás subprocesos activados en la subrutina de espera hasta que el programa desbloquee el mutex. Por lo tanto, el predicado puede haber cambiado cuando el segundo subproceso obtiene la exclusión mutua y regresa de la subrutina de espera.

En general, cada vez que se devuelve una espera de condición, el subproceso debe volver a evaluar el predicado para determinar si puede continuar con seguridad, si debe esperar de nuevo o si debe declarar un tiempo de espera. Un retorno de la subrutina de espera no implica que el predicado sea verdadero o falso. Se recomienda que una condición de espera se incluya en un “bucle while” que verifique el predicado.

Además: según la dificultad para crear condiciones de activación, que pueden ser impredecibles en sistemas multiproceso, los subprocesos pueden despertarse en cualquier momento por cualquier motivo. Eso se llama despertar espurio. Solución: use bucle para verificar siempre una variable de condición.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad