El Singleton clásico garantiza la creación de solo una instancia de un objeto. En Java hay varias formas de implementación, pero teniendo en cuenta la multihilo y la serialización, se deben considerar algunos matices:
public class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
enum EnumSingleton { INSTANCE; // métodos }
private Object readResolve() { return getInstance(); }
¿Es suficiente utilizar el método synchronized getInstance() para un Singleton thread-safe?
Respuesta: Sí, pero este enfoque conduce a una disminución del rendimiento, porque synchronized se llama en cada acceso a getInstance. Es más eficaz usar Double-checked Locking + volatile para instance, o usar Enum para implementar Singleton.
Ejemplo de código ineficiente:
public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }
Historia
En un sistema financiero, al implementar el singleton se olvidó añadir
volatilea la referencia instance en el double-checked locking. Como resultado, bajo alta carga, ocurrieron casos aleatorios de creación de dos instancias de clase, lo que llevó a la inconsistencia en los informes.
Historia
En una biblioteca de registro, implementaron Singleton a través de un objeto estático privado, sin embargo, durante la serialización y posterior deserialización (por ejemplo, en un entorno en clúster) surgieron varias instancias. El problema se resolvió añadiendo readResolve().
Historia
En un sistema de análisis, un desarrollador implementó un Singleton thread-safe a través del método synchronized getInstance(). En un sistema de alta carga, en el momento pico, hubo una caída brusca del rendimiento; se descubrió que las llamadas a getInstance() (miles de veces por segundo) se bloqueaban entre sí debido a una sincronización innecesaria, aunque la inicialización solo necesita hacerse una vez.