2011-08-13 16 views
36

Artykuł Wikipedii na temat Singletons wspomina o kilku wątkowych bezpiecznych sposobach implementacji struktury w Javie. Jeśli chodzi o moje pytania, zastanówmy się nad Singletonami, które mają długie procedury inicjalizacji i są dostępne dla wielu wątków naraz.Wątek bezpieczny Singletons w Javie

Po pierwsze, czy ta niewymieniona metoda jest bezpieczna dla wątków, a jeśli tak, z czym synchronizuje?

public class Singleton { 
    private Singleton instance; 

    private Singleton() { 
     //lots of initialization code 
    } 

    public static synchronized Singleton getInstance() { 
     if(instance == null) { 
      instance = new Singleton(); 
     } 
     return instance; 
    } 
} 

Po drugie, dlaczego poniższy wątek implementacji jest bezpieczny I leniwy w inicjalizacji? Co dokładnie dzieje się, gdy dwa wątki wprowadzają jednocześnie metodę getInstance()?

public class Singleton { 
    private Singleton() { 
     //lots of initialization code 
    } 

    private static class SingletonHolder { 
     public static final Singleton instance = new Singleton(); 
    } 

    public static Singleton getInstance() { 
     return SingletonHolder.instance; 
    } 
} 

Wreszcie, w drugim przykładzie, co jeśli jeden wątek dostaje instancji pierwszy i inny wątek dostaje instancję i próbuje wykonywać działania na niego przed konstruktor zakończy się w pierwszym wątku? Czy możesz wtedy wejść w stan niebezpieczny?

Odpowiedz

44

Odpowiedź 1: static synchronized metody wykorzystują obiekt klasy jako blokadę - czyli w tym przypadku Singleton.class.

Odpowiedź 2: język Java, między innymi:

  • ładunki klasy przy ich pierwszym obejrzano/używane
  • gwarancji, że przed uzyskaniem dostępu do klasy jest dozwolone, wszystkie inicjalizatory statyczne zakończyły

Te dwa fakty oznaczają, że wewnętrzna klasa statyczna nie zostanie załadowana przed wywołaniem metody getInstance(). W tym momencie i przed udostępnieniem wątku wywołującego, instancja statyczna tej klasy jest tworzona w ramach ładowania klas.

To wszystko oznacza, że ​​mamy bezpieczną leniwy załadunku, i bez żadnego potrzebę synchronizacji/zamków!

Ten wzór to wzór do użytku dla singletonów. To bije innymi wzorami, ponieważ MyClass.getInstance() jest standardem branżowym defacto dla singletonów - każdy, kto go używa, automatycznie wie, że ma do czynienia z singletonem (z kodem, zawsze dobrze jest być oczywistym), więc ten wzór ma właściwe API i prawidłowa implementacja pod maską.

btw Bill Pugh's article jest warta przeczytania dla kompletności przy zrozumieniu wzorców singletowych.

+0

Po przeczytaniu tego artykułu, czy mam rację mówiąc, że Java wykonuje "wewnętrzną" synchronizację podczas ładowania pól statycznych? – donnyton

+7

_ "Ten wzorzec jest wzorcem do użycia w przypadku singletonów." _ - a co z [Effective Java's enum singleton] (http://stackoverflow.com/questions/427902/java-enum-singleton)? –

+3

IMHO enum singleton nie jest tak czysty i oczywisty jak ten, a zatem nie jest tak dobry: 'MyClass.getInstance()' jest standardem branżowym dla singletonów - każdy, kto używa go automatycznie (powinien) wie, że ma do czynienia z singleton. Ten wzór ma właściwe API * i * właściwą implementację pod maską. – Bohemian

Powiązane problemy