Al ver varias preguntas relacionadas con el bloqueo y (casi) siempre encontrar el término 'bucle debido a términos espurios de despertar' 1 Me pregunto, ¿alguien ha experimentado este tipo de activación (suponiendo un entorno de hardware / software decente, por ejemplo)?
Sé que el término 'espurio' no significa una razón aparente, pero ¿cuáles pueden ser las razones de este tipo de evento?
( 1 Nota: no estoy cuestionando la práctica de bucle).
Editar: Una pregunta auxiliar (para aquellos a quienes les gustan los ejemplos de código):
Si tengo el siguiente programa y lo ejecuto:
public class Spurious {
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition cond = lock.newCondition();
lock.lock();
try {
try {
cond.await();
System.out.println("Spurious wakeup!");
} catch (InterruptedException ex) {
System.out.println("Just a regular interrupt.");
}
} finally {
lock.unlock();
}
}
}
¿Qué puedo hacer para despertar esto await
espuriamente sin esperar por siempre un evento aleatorio?
java
multithreading
locking
spurious-wakeup
akarnokd
fuente
fuente
pthread_cond_wait()
la pregunta real es "¿Por qué pthread_cond_wait tiene despertadores espurios?" .Respuestas:
El artículo de Wikipedia sobre despertares espurios tiene este dato :
Resumen : si se señala un proceso de Linux, sus subprocesos en espera disfrutarán de un agradable y espurio despertar .
Lo compro. Esa es una píldora más fácil de tragar que la razón generalmente vaga "es por rendimiento" que a menudo se da.
fuente
futex()
llamada subyacente regresaEINTR
, pero ese valor de retorno no se eleva al siguiente nivel. Por lo tanto, la persona que llama pthread debe verificar si hay una invariante. Lo que dicen es que cuandopthread_cond_wait()
regresa, debe verificar su condición de bucle (invariante) nuevamente, porque la espera podría haberse despertado espuriamente. Recibir una señal durante una llamada al sistema es una posible causa, pero no es la única.pthread
biblioteca podría proporcionar su propia lógica de verificación invariante y su propia para eliminar los espurios despertares, en lugar de pasar esa responsabilidad al usuario. Eso (presumiblemente) tendría el supuesto impacto en el rendimiento.Tengo un sistema de producción que exhibe este comportamiento. Un hilo espera una señal de que hay un mensaje en la cola. En períodos de mucha actividad, hasta el 20% de los despertares son espurios (es decir, cuando se despierta no hay nada en la cola). Este hilo es el único consumidor de los mensajes. Se ejecuta en una caja de 8 procesadores Linux SLES-10 y está construido con GCC 4.1.2. Los mensajes provienen de una fuente externa y se procesan de forma asíncrona porque hay problemas si mi sistema no los lee lo suficientemente rápido.
fuente
Para responder la pregunta en el título: ¡Sí!sucede. Aunque el artículo de Wiki menciona mucho sobre los despertares espurios, una buena explicación de lo mismo que encontré es la siguiente:
Estaba leyendo esta respuesta de Source y la encontré lo suficientemente razonable. También lee
Despiertos espurios en Java y cómo evitarlos .
PD: El enlace de arriba está en mi blog personal que tiene detalles adicionales sobre los despertares espurios.
fuente
Cameron Purdy escribió una publicación de blog hace un tiempo sobre el problema espurio de despertar. Entonces sí, sucede
Supongo que está en la especificación (como una posibilidad) debido a las limitaciones de algunas de las plataformas en las que se implementa Java. ¡aunque pueda estar equivocado!
fuente
Solo para agregar esto. Sí, sucede y pasé tres días buscando la causa de un problema de subprocesamiento múltiple en una máquina de 24 núcleos (JDK 6). 4 de 10 ejecuciones experimentaron eso sin ningún patrón. Esto nunca sucedió en 2 núcleos u 8 núcleos.
Estudié material en línea y este no es un problema de Java, sino un comportamiento general raro pero esperado.
fuente
https://stackoverflow.com/a/1461956/14731 contiene una excelente explicación de por qué debe protegerse contra las espurias activaciones, incluso si el sistema operativo subyacente no las activa. Es interesante observar que esta explicación se aplica a múltiples lenguajes de programación, incluido Java.
fuente
Respondiendo la pregunta del OP
, ¡ ningún despertar espurio podría despertar este hilo en espera!
Independientemente de si los despertares espurios pueden o no suceder en una plataforma en particular, en el caso del fragmento del OP, es positivamente imposible para
Condition.await()
volver y ver la línea "despertar espurias!" en la secuencia de salida.A menos que esté utilizando una biblioteca de clases Java muy exótica
Esto es porque estándar, OpenJDK 's
ReentrantLock
método' snewCondition()
devuelve losAbstractQueuedSynchronizer
's de la aplicación deCondition
interfaz, anidadoConditionObject
(por cierto, es la única aplicación deCondition
interfaz de esta biblioteca de clases), y elConditionObject
' método sawait()
sí mismo comprueba si la condición no hace se mantiene y ningún despertar espurio podría obligar a este método a regresar por error.Por cierto, puede verificarlo usted mismo, ya que es bastante fácil emular la activación espuria una vez que la
AbstractQueuedSynchronizer
implementación basada está involucrada.AbstractQueuedSynchronizer
usos de bajo nivelLockSupport
'spark
yunpark
métodos, y si se invocaLockSupport.unpark
en un hilo en esperaCondition
, esta acción no puede distinguirse de un despertar espuria.Refactorizando ligeramente el fragmento del OP,
, y no importa cuánto intente el hilo de estacionamiento (principal) intentar despertar el hilo en espera, el
Condition.await()
método nunca volverá en este caso.Los espurios despertares de
Condition
los métodos de espera se discuten en el javadoc de laCondition
interfaz . Aunque sí dice eso,y eso
pero luego agrega que
y
AbstractQueuedSynchronizer
la implementación de laCondition
interfaz hace exactamente eso: elimina cualquier posibilidad de reactivaciones espurias .Esto seguramente es válido para
ConditionObject
los métodos de espera de otros.Entonces, la conclusión es:
siempre debemos llamar
Condition.await
al bucle y verificar si la condición no se cumple, pero con OpenJDK estándar, Java Class Library nunca puede suceder . A menos que, de nuevo, utilice la Biblioteca de clases Java muy inusual (que debe ser muy muy inusual, porque otras Bibliotecas de clases Java no OpenJDK conocidas, actualmente GNU Classpath y Apache Harmony , casi extintas , parecen tener una implementación deCondition
interfaz estándar )fuente