2012-02-18 8 views

Respuesta

20

El autor asume allí que la variable done es una variable local, que no tiene ningún requisito en el Modelo de memoria Java para exponer su valor a otros hilos sin primitivas de sincronización. O dicho de otra manera: el valor de done no cambiará ni será visto por ningún código que no sea el que se muestra aquí.

En ese caso, dado que el bucle no cambia el valor de done, su valor puede ignorarse efectivamente, y el compilador puede levantar la evaluación de esa variable fuera del bucle, evitando que se evalúe en el "hot "parte del ciclo. Esto hace que el ciclo funcione más rápido porque tiene que hacer menos trabajo.

Esto funciona en las expresiones más complicadas también, tales como la longitud de una matriz:

int[] array = new int[10000]; 
for (int i = 0; i < array.length; ++i) { 
    array[i] = Random.nextInt(); 
} 

En este caso, la aplicación ingenua sería evaluar la longitud de la matriz 10.000 veces, pero dado que la matriz de variables es Nunca asignado y la longitud de la matriz nunca va a cambiar, la evaluación se puede cambiar a:

int[] array = new int[10000]; 
for (int i = 0, $l = array.length; i < $l; ++i) { 
    array[i] = Random.nextInt(); 
} 

Otras optimizaciones también se aplican aquí no relacionado con la elevación.

Espero que ayude.

+0

No lo entiendo, ¿cómo terminará el ciclo si la condición es siempre cierta? –

+2

Creo que el autor del punto de EJ es que debido a que el compilador JIT * puede * optimizar de esta manera, un programador no debería depender del valor de 'hecho' cambiando de un hilo diferente. Es posible que el compilador JIT pueda optimizar el código de este constructo y que el bucle realmente nunca termine. – ahawtho

+4

Esta optimización puede ocurrir incluso si 'done' es una instancia o variable de clase, siempre que no sea volátil. – assylias

0

Si agrega System.out.println("i = " + i); en el ciclo while. El levantamiento no funcionará, lo que significa que el programa se detiene como se esperaba. ¿El método println es seguro para subprocesos de modo que el jvm no puede optimizar el segmento de código?

0
public class StopThread { 
private static boolean stopRequested; 

private static synchronized void requestStop() { 
    stopRequested = true; 
} 

private static synchronized boolean stopRequested() { 
    return stopRequested; 
} 

public static void main(String[] args) 
       throws InterruptedException { 
    Thread backgroundThread = new Thread(new Runnable() { 
     public void run() { 
      int i = 0; 
      while (!stopRequested()) 
       i++; 
     } 
    }); 
    backgroundThread.start(); 
    TimeUnit.SECONDS.sleep(1); 
    requestStop(); 
} 
} 

el código anterior está justo en código efectiva, es equivalente volatile que utilizan para decorar el stopRequested.

private static boolean stopRequested() { 
    return stopRequested; 
} 

Si este método omite la palabra clave synchronized, este programa no está funcionando bien.
Creo que este cambio causa el alzando cuando el método omite la palabra clave synchronized.

Cuestiones relacionadas