2012-08-28 18 views
9

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?

+2

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. –

+0

@SkipHead: ¿Entonces el hilo se despierta, pero la bandera 'interrumpida' no está configurada? Eso tiene sentido, ¿puedes publicar eso como respuesta? –

Respuesta

7

Es "wakeup espuria" no "de interrupción espuria": "Un hilo también puede despertar sin haber sido notificada, interrumpida, o el tiempo de espera, una llamada de activación espuria." No se lanza InterruptedException durante una activación espuria. Como dices en los comentarios: el hilo se despierta pero el indicador interrumpido no está configurado.

2

Creo que si se piensa en la API Semaphore.acquire(), se dará cuenta de que es imposible que tenga un despertar espuria, principalmente porque la persona que llama no tendría forma de distinguir "espuria" para "normal", y por lo tanto la método sería inútil.

+0

De acuerdo, y es por eso que hice la pregunta. Asumí todo eso, y solo fui a verificar el código para validar mi suposición, pero estaba inquieto porque parecía encontrar evidencia de que podría ocurrir una falsa falla, así que pedí confirmar aquí. –

Cuestiones relacionadas