5

Estoy leyendo acerca de bloqueo de doble verificación desde Effective Java.
El código hace lo siguiente:¿Cómo ayuda la asignación a una variable local aquí?

private volatile FieldType field; 
FieldType getField() { 
    FieldType result = field; 
    if (result == null) { // First check (no locking) 
     synchronized(this) { 
     result = field; 
     if (result == null) // Second check (with locking) 
      field = result = computeFieldValue(); 
     } 
    } 
    return result; 
}  

Se dice que el uso de result parece que no sean necesarios, pero en realidad asegura que el field solamente se lee sólo una vez en el caso común donde ya se ha inicializado.
Pero no entiendo esto.
¿Cuál es la diferencia con hacer if(field == null) directamente?
No entiendo por qué if (result == null) es diferente, y mucho menos mejor como se indica.
¿Alguna ayuda entendiendo esto por favor?

+2

¿El 'resultado 'se usa más adelante en el método? –

+1

Nos gustaría ver "etc" ... ¿Cuál es la referencia de página para Java efectivo? No tengo mi copia conmigo, pero otros podrían. –

+0

@VictorSorokin: Consulte la actualización – Jim

Respuesta

4

El pensamiento en ese ejemplo es que el resultado/campo se usará más de una vez más abajo, supongo. El acceso al result es más económico (no es volátil).

Tiene una segunda lectura volátil al hacer la devolución de lo contrario.

Utilice en su lugar el patrón de inicialización bajo demanda si necesita hacer esto. http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom

Agregando un poco de mis aclaraciones en los comentarios a la misma respuesta para así ... claridad:

versión corta: Una variable local puede ser sólo en un registro (uno de) la CPU (s) (y en uno de los núcleos de la CPU si es múltiple, etc.). Eso es lo más rápido posible. Se debe verificar una variable volátil para detectar cambios en otros núcleos/cachés/cpus/memoria, pero los detalles pueden ser muy específicos del hardware (líneas de caché, barreras de memoria, etc.).Pero también es específico de jvm, (el compilador del servidor de punto de acceso puede elevar variables no volátiles por ejemplo) e impone límites a las instrucciones de reordenamiento para posibles ganancias de rendimiento.

+0

Es posible que desee mencionar lo que 'volátil' implica, en Java: http://en.wikipedia.org/wiki/Volatile_variable#In_Java – ArjunShankar

+0

@Pulsar: ¿Entonces, es más costoso acceder a un' volátil'? – Jim

+0

@Jim - sí. Lee el enlace que pegué arriba. – ArjunShankar

5

La explicación está en la página siguiente (el subrayado por mí):

Lo que esta variable hace es para asegurar que el campo se leído sólo una vez en el caso común donde ya ha inicializado. Si bien no es estrictamente necesario, esto puede mejorar el rendimiento y es más elegante según los estándares aplicados a la programación concurrente de bajo nivel. En mi máquina, el método anterior es aproximadamente un 25% más rápido que la versión obvia sin una variable local.

Como referencia, la cita es de p. 284 del artículo 71: Utilice la inicialización lenta juiciosamente en Effective Java 2nd Edition.

actualización: la diferencia entre la lectura de un local, frente a una variable volátil es que el primero puede pueden optimizar mejor. Las variables volátiles no se pueden almacenar en registros o cachés, ni se pueden reordenar las operaciones de memoria en ellos. Además, leer una variable volátil puede desencadenar la sincronización de memoria entre diferentes hilos.

Ver Java concurrencia en la práctica, la sección 3.1.4: variables volátiles para más detalles.

+2

Eso realmente no responde la pregunta y el OP parece haber visto ya esa explicación. – assylias

+0

@assylias, ¿cómo "esto puede mejorar el rendimiento" no responde la pregunta? –

+1

Creo que la pregunta es: ¿cómo mejora eso el rendimiento? – assylias

Cuestiones relacionadas