java multithreading interrupt

java - ¿Necesito sincronizar una llamada con el método de interrupción?



multithreading interrupt (3)

La pregunta de @xehpuk merece más atención:

¿Por qué necesitaría la sincronización? ¿Y sobre qué objeto?

Todo el punto de la sincronización, el único punto, es proteger los datos contra la corrupción. Utilizamos la sincronización cuando es imposible que un subproceso avance el estado del programa sin crear un estado no válido temporal que otros subprocesos no puedan ver.

En ese caso, sincronizamos el bloque de código que crea el estado temporal e inválido, y también debemos sincronizar cada bloque de código que mira el estado.

Entonces, cuando hablamos de interrumpir un hilo, ¿de qué estados estamos hablando?

Bueno, sin mirar el código, parece que solo habría dos: No interrumpido e interrumpido , y ambos son válidos. No hay un estado inválido obvio para pasar de uno a otro: pasar de no interrumpido a interrumpido parece una operación atómica. Por lo tanto, un programador razonable esperaría que no haya necesidad de sincronización.

Por supuesto, puede haber algunos detalles internos que he omitido, pero los detalles internos deben ocultarse al programador. Un programador razonable esperaría que, si hay una necesidad de sincronización, entonces se encargaría del método de interrupt() o se documentaría muy claramente como responsabilidad del llamante.

Consultando los JavaDocs y el código fuente del método Thread.interrupt() en Java SE 7 , encontré esto:

public void interrupt() { if (this != Thread.currentThread()) checkAccess(); synchronized (blockerLock) { Interruptible b = blocker; if (b != null) { interrupt0(); // Just to set the interrupt flag b.interrupt(this); return; } } interrupt0(); //1, Outside of the synchronized block } //... private native void interrupt0();

Como se puede ver, la invocación del método nativo en //1 está fuera del bloque sincronizado. Entonces, ¿es seguro si no se pone una llamada al método interrupt() en un bloque synchronized ?

Thread t; //something else t.interrupt(); //Not in a synchronized block

¿Será seguro para subprocesos? ¿Qué pasa si más de 1 hilo intentará interrumpirlo simultáneamente? ¿Cómo se comportará entonces el método nativo interrupt0 ?


Sí, la fuente dice que interrumpir un hilo muerto no tiene ningún efecto. Por lo tanto, será seguro para hilos.

Dice "La interrupción de un hilo que no está vivo no tiene por qué tener ningún efecto".

Interrumpe este hilo. A menos que el subproceso actual se interrumpa a sí mismo, lo que siempre está permitido, se invoca el método checkAccess () de este subproceso, lo que puede provocar que se genere una excepción SecurityException. Si este hilo está bloqueado en una invocación de los métodos wait (), wait (long) o wait (long, int) de la clase Object, o de join (), join (long), join (long, int) , sleep (long), o sleep (long, int), métodos de esta clase, luego su estado de interrupción se borrará y recibirá una InterruptedException. Si este subproceso está bloqueado en una operación de E / S en un java.nio.channels.InterruptibleChannel interruptiblechannel, el canal se cerrará, se establecerá el estado de interrupción del thread y el subproceso recibirá una java.nio.channels.ClosedByInterruptException. Si este subproceso está bloqueado en un java.nio.channels.Selector, el estado de interrupción del subproceso se establecerá y regresará inmediatamente de la operación de selección, posiblemente con un valor distinto de cero, como si el selector java.nio.channels Se invocó el método de activación del selector. Si no se cumple ninguna de las condiciones anteriores, se establecerá el estado de interrupción de este hilo. Interrumpir un hilo que no está vivo no necesita tener ningún efecto.


Yo diría que sí ... es seguro para subprocesos.

Razones:

  1. Si fuera necesario que las aplicaciones llamen a interrupt() en un bloque synchronized , entonces la especificación (el javadoc) diría que sí, y también diría qué objeto necesitaba sincronizar para obtener seguridad de subprocesos. De hecho, el javadoc no dice nada sobre esto.

  2. Si fuera necesario que las aplicaciones llamen a interrupt() en un bloque synchronized , entonces el Tutorial de Java de Oracle sobre concurrencia lo mencionaría en esta página . No lo hace

  3. Si la sincronización externa en el objeto Thread era necesaria para que la llamada interrupt() segura para threads, entonces es difícil explicar por qué el método también está haciendo una sincronización interna. (Podrían / ​​hubieran sincronizado todo el método si fuera necesario).

La evidencia anterior es (OMI) convincente, aunque no es una prueba absoluta. Si desea una prueba de que interrupt() es seguro para subprocesos, lo obtendrá mediante un análisis exhaustivo de la implementación del código nativo para interrupt0() . No he mirado el código nativo, pero espero que interrupt0 sea ​​internamente seguro para subprocesos, y eso es suficiente para que el método de interrupt seguro para subprocesos.