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
Související články
Související epizody CZ Podcastu
- #3 · Java 6 SE, Vývoj webových aplikací
Dagi a Filemon o novinkách v Javě 6 a webových frameworcích.
- #1 · Vývojová prostředí v Javě
První díl CZ Podcastu se věnuje vývojovým prostředím pro Javu.