multithreading - threading - ¿Qué implementaciones de Condición no requieren hilo actual para mantener el bloqueo?
threading get_ident() (1)
Recientemente leí algunos ejemplos del Capítulo 8 de El arte de la programación multiprocesador , sobre " Monitores y sincronización de bloqueo " que usan signalAll()
de un objeto Condition
, sin la adquisición del bloqueo asociado con esa Condition
.
Sorprendentemente, no encontré ninguna solución para esos ejemplos en la errata del libro . Además, proponen una corrección para el ejemplo de la figura 8.12 de un FifoReadWriteLock
, pero siguen utilizando el signalAll()
sin el bloqueo mantenido. Eso me perturbó y traté de encontrar otras consideraciones sobre estos ejemplos para comprender las razones por las que estos ejemplos de Java se escribieron de esta manera.
Por ejemplo, la respuesta a la pregunta " ¿Cómo funciona un mutex / lock de lectura / escritura? "Muestra el mismo ejemplo de la implementación de un FifoReadWriteLock
, que implementa el writeUnlock()
como:
void writeUnlock() {
writer = false;
condition.signalAll();
}
Acerca de la ausencia de la adquisición de bloqueo, puede leer dos motivos diferentes:
- solo utilícelo como pseudo código
- alguna implementación de una variable de condición no requiere que el bloqueo se mantenga señalizado.
Es difícil aceptar el primer argumento ya que el libro usa ejemplos en Java y explícitamente dice:
El libro usa el lenguaje de programación Java.
Sobre el segundo punto, sé que la API de Java en java.util.concurrent.locks.Condition
establece para el método signal()
:
Una implementación puede (y normalmente lo hace) requerir que el hilo actual mantenga el bloqueo asociado con esta
Condition
cuando seCondition
este método.
Si "solo una implementación puede ", eso significa que NO es obligatorio. Sin embargo, a mi leal saber y entender, no encuentro ninguna implementación que NO cumpla con este requisito. Entonces, me gustaría saber qué implementaciones de la Condition
de Java no requieren el hilo actual para mantener el bloqueo.
No conozco ninguna implementación de Condition
en el JDK que permita esperar o señalizar sin tener el monitor al mismo tiempo.
Prácticamente todas las clases java.util.concurrent
se basan en AbstractQueuedSynchronizer
que establece el mismo contrato que los métodos de monitor integrados wait()
notify()
/ notifyAll()
/ notifyAll()
para las variables de condición que proporciona, es decir, requiere poseer el bloqueo interno para permitir la llamada await()
/ signal()
/ signalAll()
.
Si prueba un ejemplo simple utilizando el FifoReadWriteLock
propuesto, encontrará que arroja una cantidad seria de IllegalMonitorStateExceptions
cortesía de su método writeUnlock()
. Estas excepciones desaparecen si aplica el enfoque lock-try-finally de los otros métodos.
Si bien la posesión del monitor no es absolutamente necesaria para esperar o señalizar, a menudo es el enfoque preferible, ya que lo salva de las lecturas de estado dinámico, no debería ser demasiado costoso como la transferencia entre los conjuntos de espera internos del mismo monitor aún se puede hacer de manera bastante eficiente, y porque la mayoría de las veces lo necesita tanto para la señalización como para la programación, en lugar de solo la señalización.