Bloqueo de doble verificación. En general.
El paradigma, del cual comencé a aprender los problemas cuando trabajaba en BEA, es que la gente verificará un singleton de la siguiente manera:
public Class MySingleton {
private static MySingleton s_instance;
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) { s_instance = new MySingleton(); }
}
return s_instance;
}
}
Esto nunca funciona, porque otro hilo podría haber entrado en el bloque sincronizado y s_instance ya no es nulo. Entonces, el cambio natural es hacerlo:
public static MySingleton getInstance() {
if(s_instance == null) {
synchronized(MySingleton.class) {
if(s_instance == null) s_instance = new MySingleton();
}
}
return s_instance;
}
Eso tampoco funciona, porque el modelo de memoria Java no lo admite. Debe declarar s_instance como volátil para que funcione, e incluso entonces solo funciona en Java 5.
Las personas que no están familiarizadas con las complejidades del modelo de memoria Java lo estropean todo el tiempo .