Sim, é necessário. Existem vários métodos que você pode usar para obter segurança de thread com inicialização lenta:
Sincronização Draconiana:
private static YourObject instance;
public static synchronized YourObject getInstance() {
if (instance == null) {
instance = new YourObject();
}
return instance;
}
Esta solução requer que cada thread seja sincronizado quando, na realidade, apenas os primeiros precisam ser.
Verifique a sincronização :
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;
}
Essa solução garante que apenas os primeiros poucos threads que tentarem adquirir seu singleton tenham que passar pelo processo de aquisição do bloqueio.
Inicialização sob demanda :
private static class InstanceHolder {
private static final YourObject instance = new YourObject();
}
public static YourObject getInstance() {
return InstanceHolder.instance;
}
Essa solução aproveita as garantias do modelo de memória Java sobre a inicialização de classe para garantir a segurança do thread. Cada classe só pode ser carregada uma vez e só será carregada quando for necessário. Isso significa que a primeira vez que getInstance
é chamada, InstanceHolder
será carregada e instance
criada, e como isso é controlado por ClassLoader
s, nenhuma sincronização adicional é necessária.