Dado el siguiente código Java:Java wait()/join(): ¿Por qué esto no es un punto muerto?
public class Test {
static private class MyThread extends Thread {
private boolean mustShutdown = false;
@Override
public synchronized void run() {
// loop and do nothing, just wait until we must shut down
while (!mustShutdown) {
try {
wait();
} catch (InterruptedException e) {
System.out.println("Exception on wait()");
}
}
}
public synchronized void shutdown() throws InterruptedException {
// set flag for termination, notify the thread and wait for it to die
mustShutdown = true;
notify();
join(); // lock still being held here, due to 'synchronized'
}
}
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start();
try {
Thread.sleep(1000);
mt.shutdown();
} catch (InterruptedException e) {
System.out.println("Exception in main()");
}
}
}
La ejecución de este esperará durante un segundo y luego salir correctamente. Pero eso es inesperado para mí, espero que ocurra un bloqueo de seguridad aquí.
Mi razonamiento es el siguiente: MyThread recién creado ejecutará run(), que se declara como 'sincronizado', por lo que puede llamar a wait() y leer con seguridad 'mustShutdown'; durante esa llamada a wait(), el bloqueo se libera y se vuelve a adquirir al regresar, como se describe en la documentación de wait(). Después de un segundo, el subproceso principal ejecuta shutdown(), que se sincroniza de nuevo para no tener acceso a mustShutdown al mismo tiempo que lo está leyendo el otro subproceso. A continuación, activa el otro hilo mediante notify() y espera a que se complete mediante join().
Pero, en mi opinión, no hay forma de que el otro subproceso vuelva de wait(), ya que necesita volver a adquirir el bloqueo en el objeto de subproceso antes de volver. No puede hacerlo porque shutdown() aún mantiene el bloqueo mientras está dentro de join(). ¿Por qué todavía funciona y sale correctamente?
Su debido a los efectos secundarios de este tipo de rosca que se extiende directamente está mal visto. Debes implementar un Runnable que envuelves con un Thread. –