Ich glaube nicht, dass jemand die Frage tatsächlich beantwortet hat , also werde ich es versuchen.
Das Flüchtige und das Erste if (instance == null)
sind nicht "notwendig". Die Sperre macht diesen Code threadsicher.
Die Frage ist also: Warum sollten Sie die erste hinzufügen if (instance == null)
?
Der Grund ist vermutlich, zu vermeiden, dass der gesperrte Codeabschnitt unnötig ausgeführt wird. Während Sie den Code innerhalb der Sperre ausführen, wird jeder andere Thread blockiert, der versucht, diesen Code ebenfalls auszuführen. Dies verlangsamt Ihr Programm, wenn Sie versuchen, häufig von vielen Threads aus auf den Singleton zuzugreifen. Abhängig von der Sprache / Plattform kann es auch zu Overheads des Schlosses kommen, die Sie vermeiden möchten.
Die erste Nullprüfung wird also hinzugefügt, um schnell festzustellen, ob Sie die Sperre benötigen. Wenn Sie den Singleton nicht erstellen müssen, können Sie die Sperre vollständig umgehen.
Sie können jedoch nicht überprüfen, ob die Referenz null ist, ohne sie auf irgendeine Weise zu sperren, da sie aufgrund des Prozessor-Caching von einem anderen Thread geändert werden könnte und Sie einen "veralteten" Wert lesen würden, der dazu führen würde, dass Sie die Sperre unnötig betreten. Aber Sie versuchen, eine Sperre zu vermeiden!
Sie machen den Singleton also flüchtig, um sicherzustellen, dass Sie den neuesten Wert lesen, ohne eine Sperre verwenden zu müssen.
Sie benötigen weiterhin das innere Schloss, da flüchtig Sie nur während eines einzelnen Zugriffs auf die Variable schützt - Sie können es nicht sicher testen und einstellen, ohne ein Schloss zu verwenden.
Ist das wirklich nützlich?
Nun, ich würde sagen "in den meisten Fällen nein".
Wenn Singleton.Instance aufgrund der Sperren zu Ineffizienz führen kann, warum rufen Sie es dann so häufig auf, dass dies ein erhebliches Problem darstellt ? Der springende Punkt eines Singletons ist, dass es nur einen gibt, sodass Ihr Code die Singleton-Referenz einmal lesen und zwischenspeichern kann.
Der einzige Fall, in dem ich mir vorstellen kann, wo dieses Caching nicht möglich wäre, wäre, wenn Sie eine große Anzahl von Threads haben (z. B. könnte ein Server, der einen neuen Thread zum Verarbeiten jeder Anforderung verwendet, Millionen von sehr kurz laufenden Threads erstellen, von denen jeder die Singleton.Instance einmal aufrufen müsste).
Ich vermute also, dass doppelt geprüftes Sperren ein Mechanismus ist, der in ganz bestimmten leistungskritischen Fällen einen echten Platz hat, und dann sind alle auf den Zug "Dies ist der richtige Weg, dies zu tun" geklettert, ohne wirklich darüber nachzudenken, was er tut und ob er es tut wird tatsächlich notwendig sein, wenn sie es für verwenden.