In Java-Programmen kann es manchmal notwendig sein, einige Hochschulobjekt-Initialisierungsvorgänge zu verschieben, und werden nur bei der Verwendung dieser Objekte initialisiert. Dies wird als verzögerte Initialisierung oder faule Laden bezeichnet
Schauen Sie sich eine unsichere Verzögerungsinitialisierung an:
Nachdem Thread A ausgeführt wurde 1, wird festgestellt, dass die Objektinstanz null ist und bereit ist, es neu zu machen, während Thread B zuerst neu ist, was einen Fehler verursacht.
Wir können Synchronisationsschlösser verwenden, um die Korrektheit sicherzustellen:
Die Synchronisierung der gesamten Methode ist jedoch zu teuer, und die Leute haben sich doppelt Check -Locking ausgedacht:
Die im Mindestbereich verwendete Synchronisationsschloss scheint den Zweck zu erreichen, das doppelte Überprüfungen zu verwenden. Dies hat jedoch ein Problem: Wenn A Thread 4 ausführt, wurde Thread Bs 7 noch nicht ausgeführt, und Thread A bestimmt Instanz! = Null. Thread Bs 7 wurde noch nicht ausgeführt. Warum passiert das also?
Schauen Sie sich die zugrunde liegende wichtige Implementierung von New Instance () an:
Tatsächlich soll zuerst 1 Speicher ausführen, dann das Objekt initialisiert und die Instanz festgelegt werden. Dann gibt es hier eine Neuordnung, und die Reihenfolge von 2 und 3 kann ersetzt werden:
Wenn B noch 7 ausführt, bestimmt A um 4, dass das Instanzobjekt initialisiert wurde. Wenn die Instanz vor CtorinStance (Speicher) aufgerufen wird, verursacht ein Fehler.
Es gibt zwei Lösungen:
1. Deklarieren Sie das Instanzobjekt als volatil, es verbietet die Neuordnung von 2 und 3
2. Verwenden einer Lösung basierend auf Klasseninitialisierung: Die JVM führt die Klasseninitialisierung in der Initialisierungsstufe der Klasse durch (dh nach dem Laden der Klasse und bevor sie vom Thread verwendet wird). existieren
Während der Initialisierung der Ausführungsklasse wird die JVM ein Schloss erwerben. Dieses Schloss kann die Initialisierung derselben Klasse durch mehrere Threads synchronisieren
Wir werden feststellen, dass der Implementierungscode des auf der Klasseninitialisierung basierenden Schemas einfacher ist. Das auf volatilen Basis basierende Doppelprüfungsschema hat jedoch einen zusätzlichen Vorteil: Zusätzlich zur Verzögerung der Initialisierung statischer Felder kann es auch die Initialisierung der Instanzfelder verzögern. Die Initialisierung der Feldverzögerung reduziert den Overhead der Initialisierungsklassen oder das Erstellen von Instanzen, erhöht jedoch den Aufwand von Zugriffsfeldern, die initialisiert werden. Meistens ist die normale Initialisierung besser als eine verzögerte Initialisierung. Wenn Sie wirklich die späte Initialisierung von Thread-Safe verwenden müssen, beispielsweise Felder, verwenden Sie bitte das oben beschriebene volatile Verzögerungsinitialisierungsschema. Wenn Sie wirklich die späte Initialisierung von Thread-Safe für statische Felder verwenden müssen, verwenden Sie bitte das oben beschriebene klassenbasierte Initialisierungsschema.
Zusammenfassen
Das obige ist der Implementierungscode von Java Double Check Lock, der vom Editor eingeführt wurde. Ich hoffe, es wird für alle hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird allen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!