La versione corretta senza blocco a doppio controllo è:
lock (myLock) {
if (mySingleton == null) { // 2nd (double) check
mySingleton = new MySingleton();
}
}
Tuttavia ciò richiede l'operazione costosa di ottenere un lock ogni volta che si desidera ottenere il singleton, tuttavia il blocco è in realtà necessario solo una volta (durante la prima inizializzazione).
Quindi è stato introdotto il double check dove un thread controllerà mySingleton al di fuori del lock e se passa il primo check ( mySingleton
non è null
) allora non è necessario preoccuparsi di acquisire il lock.
Il controllo interno rimane per evitare la condizione di competizione quando 2 thread raggiungono il blocco di blocco per inizializzare mySingleton
, tuttavia ciò può causare una doppia inizializzazione se il controllo interno non è presente (2 thread vanno nel blocco di blocco attivo al momento ).
Aggiungere un terzo controllo è inutile, ci sono solo 2 stati reali qui: all'esterno della serratura e all'interno della serratura. Dove metteresti il terzo controllo?