Si, es necesario. Hay varios métodos que puede utilizar para lograr la seguridad de los subprocesos con la inicialización diferida:
Sincronización draconiana:
private static YourObject instance;
public static synchronized YourObject getInstance() {
if (instance == null) {
instance = new YourObject();
}
return instance;
}
Esta solución requiere que todos los subprocesos estén sincronizados cuando en realidad solo deben estar los primeros.
Verifique la sincronización :
private static final Object lock = new Object();
private static volatile YourObject instance;
public static YourObject getInstance() {
YourObject r = instance;
if (r == null) {
synchronized (lock) { // While we were waiting for the lock, another
r = instance; // thread may have instantiated the object.
if (r == null) {
r = new YourObject();
instance = r;
}
}
}
return r;
}
Esta solución asegura que solo los primeros hilos que intentan adquirir su singleton tengan que pasar por el proceso de adquisición del candado.
Inicialización a pedido :
private static class InstanceHolder {
private static final YourObject instance = new YourObject();
}
public static YourObject getInstance() {
return InstanceHolder.instance;
}
Esta solución aprovecha las garantías del modelo de memoria de Java sobre la inicialización de clases para garantizar la seguridad de los subprocesos. Cada clase solo se puede cargar una vez y solo se cargará cuando sea necesario. Eso significa que la primera vez que getInstance
se llama, InstanceHolder
se cargará y instance
se creará, y dado que esto está controlado por ClassLoader
s, no es necesaria ninguna sincronización adicional.