Desbloqueo espurio en hilo de impulso
-
05-07-2019 - |
Pregunta
Encontré este interesante párrafo en Aumente la documentación del hilo hoy:
void wait(boost::unique_lock<boost::mutex>& lock)
...
Efectos: Llamada atómicamente lock.unlock () y bloquea el hilo actual. los el hilo se desbloqueará cuando lo notifique un llame a este- > notify_one () o this- > notify_all (), o espuriamente . Cuando el hilo está desbloqueado (para cualquiera que sea la razón), la cerradura es readquirido invocando lock.lock () antes de que vuelva la llamada a esperar. los la cerradura también se recupera invocando lock.lock () si la función sale con una excepción.
Entonces, lo que me interesa es el significado de la palabra "espuriamente". ¿Por qué se desbloqueará el hilo por razones espurias? ¿Qué se puede hacer para resolver esto?
Solución
Este artículo de Anthony Williams es particularmente detallado .
No se pueden predecir estelas espurias: son esencialmente al azar de la punto de vista del usuario. Sin embargo, ellos comúnmente ocurre cuando la biblioteca de hilos no puede garantizar de manera confiable que una espera hilo no perderá una notificación. Dado que una notificación perdida haría inutilizar la variable de condición, la biblioteca de hilos despierta el hilo de su espera en lugar de tomar el riesgo.
También señala que no debe usar las sobrecargas timed_wait
que toman una duración, y generalmente debe usar las versiones que toman un predicado
Ese es el error del principiante, y uno eso se supera fácilmente con un simple regla: siempre verifique su predicado en un bucle cuando espera con una condición variable. El error más insidioso viene de timed_wait ().
Este artículo de Vladimir Prus también es interesante.
Pero, ¿por qué necesitamos el bucle while? no podemos escribir:
if (!something_happened)
c.wait(m);
No podemos. Y la razón asesina es que 'esperar' puede regresar sin ninguna llamada de 'notificar'. Eso se llama despertar espurio y es permitido explícitamente por POSIX. Esencialmente, regrese solo de 'esperar' indica que los datos compartidos podrían han cambiado, por lo que los datos deben ser evaluado de nuevo.
Bien, entonces ¿por qué esto aún no se ha solucionado? La primera razón es que nadie quiere arreglarlo. Llamada de cierre para 'esperar' en un bucle es muy deseado por varios otras razones. Pero esas razones requieren explicación, mientras que es espuria wakeup es un martillo que se puede aplicar a cualquier estudiante de primer año sin fallar.
Otros consejos
Esta publicación de blog da una razón para Linux, en términos de la llamada al sistema futex
que regresa cuando se entrega una señal a un proceso. Desafortunadamente no explica nada más (y de hecho está pidiendo más información).
La entrada de Wikipedia sobre espurias despertares (que parecen ser un concepto de posix, por cierto, no limitado a impulsar) puede interesarle también.