Myślę, że nikt nie odpowiedział na to pytanie , więc spróbuję.
Zmienne i pierwsze if (instance == null)
nie są „konieczne”. Blokada sprawi, że ten kod będzie bezpieczny dla wątków.
Więc pytanie brzmi: dlaczego miałbyś dodać pierwszy if (instance == null)
?
Powodem jest przypuszczalnie unikanie niepotrzebnego wykonywania zablokowanej sekcji kodu. Podczas wykonywania kodu wewnątrz zamka każdy inny wątek, który próbuje również wykonać ten kod, jest blokowany, co spowolni twój program, jeśli będziesz często próbował uzyskać dostęp do singletona z wielu wątków. W zależności od języka / platformy mogą również występować narzuty związane z samym zamkiem, których chcesz uniknąć.
Tak więc pierwsze sprawdzenie zerowe jest dodawane jako naprawdę szybki sposób sprawdzenia, czy potrzebujesz blokady. Jeśli nie musisz tworzyć singletona, możesz całkowicie uniknąć blokady.
Ale nie możesz sprawdzić, czy odwołanie jest zerowe bez blokowania go w jakiś sposób, ponieważ z powodu buforowania procesora inny wątek mógłby go zmienić i odczytać „nieaktualną” wartość, która prowadziłaby do niepotrzebnego wejścia do blokady. Ale próbujesz uniknąć blokady!
Więc sprawiasz, że singleton jest zmienny, aby mieć pewność, że czytasz najnowszą wartość, bez konieczności używania blokady.
Nadal potrzebujesz wewnętrznego zamka, ponieważ niestabilność chroni Cię tylko podczas pojedynczego dostępu do zmiennej - nie możesz go bezpiecznie przetestować i ustawić bez użycia zamka.
Czy to rzeczywiście przydatne?
Cóż, powiedziałbym „w większości przypadków nie”.
Jeśli Singleton.Instance może powodować nieefektywność z powodu blokad, to dlaczego dzwonisz do niego tak często, że byłby to znaczący problem ? Cały sens singletona polega na tym, że jest tylko jeden, więc kod może raz odczytać i buforować pojedyncze odniesienie.
Jedynym przypadkiem, w którym mogę wymyślić, gdzie to buforowanie nie byłoby możliwe, byłby, gdy masz dużą liczbę wątków (np. Serwer używający nowego wątku do przetwarzania każdego żądania może tworzyć miliony bardzo krótko działających wątków, każdy z co musiałoby raz zadzwonić do Singleton.Instance).
Podejrzewam więc, że podwójnie sprawdzane blokowanie jest mechanizmem, który ma realne miejsce w bardzo specyficznych przypadkach krytycznych dla wydajności, a następnie każdy wdrapał się na modę „to jest właściwy sposób”, nie zastanawiając się, co robi będzie faktycznie konieczne w przypadku, gdy go używają.