java - example - thread safety php
¿Por qué este código no arroja una NullPointerException? (1)
Dos cosas:
Thread.sleep (0) aún detiene la ejecución (potencialmente más de 0 milisegundos). Básicamente, incluso un sueño 0 hace que la ejecución en ese hilo se detenga brevemente y luego se reinicia. Esto le da al otro hilo la oportunidad de correr y terminar, por lo que puedes activar la condición de carrera.
los archivos deben ser
volatile
; de lo contrario, se permite que la JVM optimice de tal forma que nunca note que está cambiando el valor, porque no cree que deba mantener la coherencia entre los subprocesos.
Fondo
Me gustaría entender por qué un fragmento de código no arroja una NullPointerException.
Código fuente
Considera el siguiente código:
public class Agent {
public List files = new ArrayList();
public void deliver() {
if( files != null && files.iterator().hasNext() ) {
File file = (File)files.iterator().next();
}
files = new ArrayList();
}
}
El método de deliver
se llama repetidamente, mientras que el siguiente código se ejecuta en un hilo separado:
public void run() {
agent.files = null;
}
Solo hay una instancia de agent
único.
Problema
Una NullPointerException nunca se lanza.
Sin embargo, cuando el método de deliver
hace una pausa, incluso durante 0 milisegundos, se lanza una excepción NullPointerException como se esperaba:
public void deliver() {
if( files != null ) {
Thread.currentThread().sleep( 0 );
if( files.iterator().hasNext() ) {
File file = (File)files.iterator().next();
}
}
files = new ArrayList();
}
Tengo entendido que, en teoría, existe una condición de carrera entre verificar files == null
y llamar a files.iterator().hasNext()
. En la práctica, no puedo activar la condición de carrera sin introducir la pausa (es decir, dividir la verificación nula de la llamada al método posterior).
Pregunta
¿Por qué el primer método de deliver
no arroja una excepción cuando la verificación nula y el uso se combinan en la misma declaración?