¿Cuál es la forma más segura de escribir un Singleton thread-safe en Java?
Opciones
- Un campo public static inicializado de forma lazy y sin sincronización
- Un
enumde un solo elemento, o una holder class con una instancia static final (Opción correcta) - Una clase normal con un constructor público que cualquiera puede llamar
- Una clase con todos sus campos marcados con
volatile
Respuesta
Un enum de un solo elemento, o una holder class / instancia static final creada al arrancar
Por qué
Singleton significa una instancia para toda la aplicación. La inicialización lazy con if (instance == null) instance = new X(); NO es thread-safe: dos threads podrían crear dos instancias.
Opciones seguras:
enum Config { INSTANCE; ... }: la JVM garantiza una instancia y además resiste la serialización y los ataques por reflection (lo recomienda Effective Java).- Instancia inmediata
private static final X INSTANCE = new X();. - Initialization-on-demand holder (una clase interna private static que guarda la instancia).
- El double-checked locking solo funciona si el campo es
volatile.
En apps Spring, normalmente deja que el contenedor gestione los beans singleton.
public enum AppConfig {
INSTANCE;
public String env() { return "prod"; }
}
// AppConfig.INSTANCE.env()Recuerda
Singleton en Java: prefiere enum o deja que lo gestione Spring.