Java 5 y superior solamente. Supongamos una computadora de memoria compartida multiprocesador (probablemente esté usando una en este momento).¿La palabra clave Java sincronizada vacía el caché?
Aquí es un código de inicialización perezosa de un producto único:
public final class MySingleton {
private static MySingleton instance = null;
private MySingleton() { }
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
}
¿Tiene instance
tienen que ser declarado volatile
con el fin de impedir que el optimizador de reescritura getInstance() de la siguiente manera (lo que sería correcto en un secuencial programa):
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
// instance must be null or we wouldn't be here (WRONG!)
instance = new MySingleton();
}
}
}
Suponiendo que el optimizador no volver a escribir el código, si no se ha declarado instance
volatile
está todavía garantizada para ser enviado a la memoria cuando se sale del bloque synchronized
y se lee desde la memoria cuando se ingresa el bloque synchronized
?
EDITAR: Olvidé hacer que getInstance() static. No creo que eso cambie la validez de las respuestas; todos sabían lo que quería decir.
Sugerencia: puede usar 'javap -c com.example.ClassName' para desensamblar el código, de modo que pueda verificar cómo se ha compilado y si el compilador ha cambiado/optimizado uno u otro. Lo revisé con el de JDK 1.6 y el compilador no eliminó el 'si' anidado. – BalusC
Usar javap es interesante, pero el optimizador en javac suele ser bastante pobre. A propósito. El optimizador real está en el compilador JIT en tiempo de ejecución. – Darron
Pido disculpas por comprobar solo una de las respuestas como "La respuesta". Todos ellos hasta ahora merecen ser revisados, pero solo me permite verificar uno. –