Un problema aparentemente sencillo: Tengo un java.util.concurrent.Semaphore
, y quiero adquirir un permiso de uso de acquire()
.¿Puede Semaphore.acquire() lanzar InterruptedException debido a una activación espuria?
se especifica el método de tirar acquire()
InterruptedException
si el hilo se interrumpe:
Si el hilo actual:
- ha fijado su estado interrumpido en la entrada a este método; o
- se interrumpe a la espera de un permiso,
continuación InterruptedException se lanza y el estado de interrupción del hilo actual se borra.
Sin embargo, el patrón habitual con métodos que puedan arrojar InterruptedException
es llamarlos en un bucle, ya que las discusiones pueden ser objeto de activaciones falsas que se parecen lo mismo que ser interrumpido. Por ejemplo, el documentation for Object.wait(long)
dice:
Un hilo también puede despertar sin ser notificado, interrumpida, o el tiempo de espera, la llamada de activación espuria. Si bien esto raramente ocurrirá en la práctica, las aplicaciones deben evitarlo al probar la condición que debería haber provocado el despertar del hilo y continuar esperando si la condición no se cumple. En otras palabras, las esperas siempre deben ocurrir en bucles.
Así que la pregunta es, ¿está Semaphore.acquire()
sujeto al mismo tipo de activación espuria? La respuesta lógica sería "no", pero no puedo encontrar ninguna evidencia para eso, y de hecho la evidencia parece apuntar en la otra dirección.
Mirando el source for Semaphore
, parece que delega la adquieren real a un AbstractQueuedSynchronizer
, que según its source delegados a LockSupport.park()
.
El documentation for LockSupport.park()
menciona explícitamente de activación espuria, pero la implementación de AbstractQueuedSynchronizer.doAcquireInterruptably()
parece que sólo echa Thread.interrupted()
y luego tirar InterruptedException
.
tanto, a menos que me falta algo (lo cual es muy posible), se observa que Semaphore.acquire()
puede tiro InterruptedException
falsamente?
¿Es correcto? Más importante aún, ¿hay algo que pueda hacer al respecto? Podría usar Semaphore.acquireUninterruptably()
, pero no quiero una espera ininterrumpida, solo una que no se interrumpa de forma espuria. ¿Hay alguna alternativa?
Es "activación espuria", no "interrupción espuria": "Un hilo también puede despertarse sin que se le notifique, interrumpa o agote el tiempo de espera, lo que se denomina activación espuria". No se lanza InterruptedException durante una activación espuria. –
@SkipHead: ¿Entonces el hilo se despierta, pero la bandera 'interrumpida' no está configurada? Eso tiene sentido, ¿puedes publicar eso como respuesta? –