Entonces, si he entendido esto correctamente, un hilo entra en estado de espera cuando llamamos a esperar en un objeto y entra en estado bloqueado cuando está esperando un bloqueo en un objeto (como cuando intenta entrar en un bloque o método sincronizado ).

Sin embargo, ¿cómo los métodos de E / S como read () ponen un hilo en un estado bloqueado? Entiendo POR QUÉ tiene que estar en un estado bloqueado, esperando datos que pueda leer, pero también estoy interesado en CÓMO. ¿Cómo notifica la JVM al subproceso que puede continuar cuando los datos del recurso que está intentando leer están disponibles de nuevo?

5
Per Nissilä 14 dic. 2016 a las 14:48

2 respuestas

La mejor respuesta

No cambia el estado del hilo a BLOQUEADO

public static void main(String[] args) throws IOException {
    Thread main = Thread.currentThread();
    new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            System.out.println(main + " is in "+main.getState()+" state");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new AssertionError(e);
            }
        }
    }).start();
    System.in.read();
}

Huellas dactilares

Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state

En cambio, el sistema operativo no regresa del read hasta que hay algunos datos y el sistema operativo decide si y cuándo cambiar de contexto el hilo / proceso.

¿Cómo notifica la JVM al subproceso que puede continuar cuando los datos del recurso que está intentando leer están disponibles de nuevo?

El sistema operativo despierta el hilo cuando hay más datos o se ha cerrado la transmisión. La JVM no se involucra.

6
Peter Lawrey 14 dic. 2016 a las 12:36

Esto depende de la plataforma nativa.

En POSIX, una llamada a read generalmente bloquea hasta hay datos disponibles, pero hay muchas otras razones para regresar, como que se alcanzó el final del archivo, se cerró el descriptor del archivo, se agotó el tiempo de espera de la operación o una señal interrumpió la operación.

En Windows, la función más estrechamente relacionada es ReadFile.


Los detalles sangrientos, en referencia a la actualización 112 b15 de Java 8:

FileInputStream.read llama al nativo FileInputStream.read0, implementado de forma nativa a través de JNI en Java_java_io_FileInputStream_read0, que llama a readSingle, que llama a {{X3 }}.

En POSIX, IO_Read se define como handleRead, que llama a read. RESTARTABLE la macro se repite mientras hay un error y el errno es EINTR.

En Windows, IO_Read se define como handleRead, que llama a ReadFile.

0
acelent 14 dic. 2016 a las 15:12