dagblog.
← Archiv

Singleton a problém Double-check lockingu


Pokud jste již někdy používali návrhový vzor Singleton ve
 vícevláknovém prostředí, tak jste zřejmě narazili na problém jedinečnosti
 Singletonu resp. synchronizaci metody, která vrací jeho instanci.
 Synchronizovat celou metodu vracející instanci, se nevyplatí z hlediska vzájemného 
 zdržování jednotlivých vláken.

V některých materiálech se proto uvádí technika tzv. double-check lockingu
 (dvojité kontroly s uzamčením), která vypadá následovně

.
.
.
public static Singleton getInstance() {
if(singleton == null) {
synchronized(Singleton.class) {
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}

Tato technika je založena na tom, že se synchronizuje pouze 
 vytvoření instance Singletonu to pouze v případě,
 že je Singleton neinicializován(singleton == null)
 v synchronizovaném bloku.

Tento kód je teoreticky dobrý ovšem prakticky je nepoužitelný! Na vině je pamětový
 model Javy, který umožňuje tzv. Out-of-order zápis. V podstatě se jedná o to, že
 reference na objekt nemusí být rovná null(je již alokována paměť na haldě s ukazatelem na
 zásobníku) a objekt ještě není zinicializován(je volán jeho konstruktor). Out-of-order zapís je zavlečen
 JIT kompilátorem.

Řešení se nabízí více a každé má své pro a proti. Například v použití statické třídní proměnné
 nebo proměnné typu volatile, u které nesmí JIT kompilátor provést Out-of-order.
 Více o tomto problému Peter Haggar 
 v článku Double-checked locking and the Singleton pattern
 a tým odborníků 
 David Bacon, Joshua Bloch, Jeff Bogda, Cliff Click, Paul Haahr, Doug Lea, Tom May, Jan-Willem Maessen, John D. Mitchell, Kelvin Nilsen, Bill Pugh, Emin Gun Sirer
 v článku The "Double-Checked Locking is Broken" Declaration

Verze na Medium

Související články

Související epizody CZ Podcastu