Newsgroup: it.comp.java
Titolo: Singleton: static synchronized oppure va bene solo static ?

Oggi ho fatto la conoscenza con il pattern "Singleton"..
..ma non ho capito bene una cosa:
il metodo getInstance() deve essere static synchronized oppure va bene
anche se è solo static ?
Cioè..
così... (static synchronized)
public class MioSingolo {
    private static MioSingolo istanza = null;
    private MioSingolo() {}
    // Metodo della classe impiegato per accedere al Singleton
    public static synchronized MioSingolo getInstance() {
        if (istanza == null)
            istanza = new MioSingolo();
        return istanza;
    }
}
oppure così... (solo static)
public class MioSingolo {
    private static MioSingolo istanza = null;
    private MioSingolo() {}
    // Metodo della classe impiegato per accedere al Singleton
    public static MioSingolo getInstance() {
        if (istanza == null)
            istanza = new MioSingolo();
        return istanza;
    }
}
Grazie

 
La sincronizzazione non fa parte del pattern. D'altronde mica è detto 
che ci sia concorenza tra gli utilizzatori.

 anche se č solo static ?
nel tuo caso a rigor di logica dovrebbe essere synchronized solo il 
blocco che contiene il controllo:
      public static MioSingolo getInstance() {
	synchronized(semaforo) {
          if (istanza == null)
              istanza = new MioSingolo();
          }
	return istanza;
      }
ciň per evitare il caso (invero molto isolato e improbabile) che i primi 
due accessi al metodo avvengano in concorrenza e creino due istanze diverse.
dichiarando "istanza" in questo modo:
private static final MioSingolo istanza = new MioSingolo();
ti togli da ogni imbarazzo.

Ho capito, allora quello che c'è scritto qui
http://www.javaworld.com/javaworld/jw-01-2001/jw-0112-singleton.html?page=5
è una baggianata:
"
Double-checked locking is another common solution but, unfortunately,
it does not work (see Listing 6).
Listing 6
// Double-checked locking -- don't use
public static MySingleton getInstance() {
    if (_instance==null) {
      synchronized (MySingleton.class) {
        if (_instance==null) {
           _instance = new MySingleton();
        }
      }
    }
}
In this situation, we intend to avoid the expense of grabbing the lock
of the singleton class every time the method is called. The lock is
grabbed only if the singleton instance does not exist, and then the
existence of the instance is checked again in case another thread
passed the first check an instant before the current thread.
Unfortunately, double-checked locking causes problems. To wit,
compiler optimizations can make the assignment of the new singleton
object before all its fields are initialized. (See "Double-checked
locking is broken" in Resources.) The only practical solution is to
synchronize the getInstance() method (as in Listing 2).
Listing 2
public class MySingleton {
    private static  MySingleton _instance;
    private MySingleton() {
        // construct object . . .
    }
    // For lazy initialization
    public static synchronized MySingleton getInstance() {
        if (_instance==null) {
            _instance = new MySingleton();
        }
        return _instance;
    }
        // Remainder of  class definition . . .
}
"

            _instance = new MySingleton();
Non per impicciarmi ma qui la sequenza č: if - blocco sincronizzato - 
if. Quella di rootkit era: if- blocco sincronizzato.
Non č proprio la stessa cosa... ;)

 č una baggianata:
anche no; semplicemente č una analisi piů dettagliata e piů attendibile 
di quella del sottoscritto :)
resta il fatto che la soluzione migliore in caso di concorrenza č la 
non-lazy, ricordando che la sincronizzazione costa e, nel caso di 
specie, serve solo alla prima chiamata.

Ricapitolando... solo static, senza synchronized:
public class MioSingolo {
    private static MioSingolo istanza = null;
    private MioSingolo() {}
    // Metodo della classe impiegato per accedere al Singleton
    public static MioSingolo getInstance() {
        if (istanza == null)
            istanza = new MioSingolo();
        return istanza;
    }
}
... giusto ?

 Ricapitolando... solo static, senza synchronized:
imho si, e se hai problemi di concorrenza evitare l'inizializzazione lazy.
come ti dicevo la sincronizzazione costa in termini di performance, nel 
caso di specie tu quel metodo lo invochi n-volte ma la necessità di 
essere thread-safe ce l'hai solo la prima volta. dopo, sono tutti lock 
inutili.


Cosa significa "imho"
e qual'è l' "l'inizializzazione lazy" così so come evitarla ?

 e qual'è l' "l'inizializzazione lazy" così so come evitarla ?
l'inizializzazione lazy (pigra) è quel meccanismo di istanziare 
l'oggetto solo all'occorrenza e quindi nella prima chiamata del metodo 
getInstance(). l'alternativa è quella che ti ho descritto qualche 
messaggio fa, ovvero di inizializzare l'istanza direttamente alla 
dichiarazione (magari dichiarandolo anche final così hai la certezza 
"formale" che non verrà modificata).

Grazie

 Grazie
Che ne dite di quest'altra implementazione:
http://www.ippatsuman.com/blog/2008/01/27/implementare-correttamente-il-pattern-singleton-in-java/
Esiste una versione ancora più elegante, lazy, thread safe e
funzionante su tutte le versioni di Java ideata da William Pugh:
// Implementazione lazy thread safe
public class MySingleton {
   private MySingleton() {}
   private static class MySingletonHolder {
     private final static MySingleton instance = new MySingleton();
   }
   public static MySingleton getInstance() {
     return MySingletonHolder.instance;
   }
}

 
IMHO al 99% si tratta di seghe mentali, visto che nel 99% dei casi puoi 
tranquillamente inizializzare il tuo singleton in un punto sicuro (allo 
startup dell'applicazione per esempio).


Ah Ok, meglio così

Usa un inizializzazione statica. Cmq non ti consiglio il sigleton:
1. e' troppo accopiante
2. gli oggetti che ereditano da signleton sono singleton? (vedi GoF
Principle of Design Pattern)
3. prediligi il Monostate Pattern
4. prediligi il Borg Pattern
5. come suggerisce Alex Martelli rileggi i punti 3 e 4.
Ciao
lopo


grazie studierò gli altri pattern da te accennati (buona cosa sapere
dell'ereditarietà del singleton)

 dell'ereditarietą del singleton)
Visto che si discute a 360 gradi
Il singleton non e' JavaEnterprise.
In un contesto JEE e' fortemente sconsigliato.
Ciao
Nicola
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/