Heim  >  Artikel  >  Java  >  So implementieren Sie den Mechanismus zur Erweiterung der synchronisierten Sperre in Java

So implementieren Sie den Mechanismus zur Erweiterung der synchronisierten Sperre in Java

WBOY
WBOYnach vorne
2023-04-28 17:13:131458Durchsuche

    synchronisiert

    In JDK 1.5 muss die Synchronisierung durch Aufrufen der Monitorsperre (Monitor) implementiert werden. Die Monitorsperre hängt im Wesentlichen von der Mutex-Sperre (Mutex-Sperre) des zugrunde liegenden Betriebssystems ab Wenn es freigegeben und erworben wird, muss es vom Benutzerstatus in den Kernelstatus konvertiert werden, was hohe Kosten verursacht und eine lange Ausführungszeit erfordert. Wir nennen diese Art von Sperre, die auf der Mutex-Sperrimplementierung des Betriebssystems basiert, ein „Schwergewicht“. sperren".

    Was sind Benutzermodus und Kernelmodus?

    Benutzermodus: Wenn ein Prozess den eigenen Code des Benutzers ausführt, befindet er sich im Benutzerausführungsstatus. Kernel-Modus: Wenn eine Aufgabe (ein Prozess) einen Systemaufruf ausführt und im Kernel-Code gefangen ist, sagen wir, dass sich der Prozess im Kernel-Laufzustand befindet. Zu diesem Zeitpunkt führt der Prozessor den Kernel-Code mit der höchsten Berechtigungsstufe aus .

    So implementieren Sie den Mechanismus zur Erweiterung der synchronisierten Sperre in Java

    Warum sind wir in Kernelmodus und Benutzermodus unterteilt?

    Angenommen, es gibt keinen Unterschied zwischen Kernelmodus und Benutzermodus, kann das Programm Hardwareressourcen nach Belieben lesen und schreiben, z. B. nach Belieben lesen, schreiben und Speicher zuweisen. Auf diese Weise kann der Programmierer versehentlich unangemessene Inhalte in a schreiben Ort, an dem es nicht geschrieben werden sollte. Es ist wahrscheinlich, dass das System abstürzt.

    Mit der Unterscheidung zwischen Benutzermodus und Kernelmodus führt das Programm bei der Ausführung eines Vorgangs eine Reihe von Überprüfungen und Inspektionen durch. Erst nachdem bestätigt wurde, dass kein Problem vorliegt, kann es die Ressourcen normal betreiben, sodass Sie sich keine Sorgen über versehentliche Probleme machen müssen Dies ist die Situation, in der das System beschädigt wird. Das heißt, die Unterscheidung zwischen Kernelmodus und Benutzermodus kann die Ausführung des Programms sicherer machen, gleichzeitig führt der Wechsel zwischen den beiden Modi jedoch zu einem gewissen Leistungsaufwand.

    Sperrenerweiterung

    Um den durch den Erwerb und die Freigabe von Sperren verursachten Leistungsverbrauch zu beheben, wurden in JDK 1.6 die Zustände „voreingenommene Sperre“ und „leichte Sperre“ eingeführt. Zu diesem Zeitpunkt hat der synchronisierte Zustand Folgendes Insgesamt 4 Zustände. Typen:

    • Kein Schloss

    • Voreingenommenes Schloss

    • Leichtes Schloss

    • Schwergewichtiges Schloss

    Die Stufen der Schlösser werden in der oben genannten Reihenfolge aufgerüstet. Wir werden upgraden Dieser Prozess wird als „Sperrenerweiterung“ bezeichnet.

    So implementieren Sie den Mechanismus zur Erweiterung der synchronisierten Sperre in Java

    PS: Bisher ist das Upgrade von Schlössern einseitig, das heißt, es kann nur von niedrig auf hoch aktualisiert werden (keine Sperre-> vorgespannte Sperre-> leichte Sperre->). ; Gewichtsstufensperre), es kommt zu keiner Sperrverschlechterung.

    Warum kann die Sperrerweiterung die Leistung von synchronisiert optimieren? Wenn wir diese Sperrzustände verstehen, werden wir natürlich die Antwort haben. Schauen wir uns das gemeinsam an.

    Voreingenommene Sperre

    HotSpot-Autor hat durch Forschung und Praxis herausgefunden, dass es in den meisten Fällen keine Multi-Thread-Konkurrenz für Sperren gibt und diese immer mehrmals von demselben Thread erworben werden, um den Erwerb von Threads zu verbilligen Schlösser, sie führten Bias Lock ein.

    Voreingenommenes Sperren bedeutet, dass der erste Thread den Zugriff auf die Sperre bevorzugt. Wenn während des Betriebs nur ein Thread auf die Synchronisierungssperre zugreift und kein Multi-Thread-Konflikt vorliegt, muss der Thread nicht ausgelöst werden. Dem Thread wird eine Bias-Sperre hinzugefügt.

    Voreingenommener Sperrenausführungsprozess

    Wenn ein Thread auf einen synchronisierten Codeblock zugreift und eine Sperre erhält, wird die sperrenvoreingenommene Thread-ID im Markierungswort des Objektheaders gespeichert. Sie wird nicht mehr durch die CAS-Operation hinzugefügt Der Thread betritt und verlässt den synchronisierten Block und entsperrt ihn. Erkennen Sie jedoch, ob die auf den aktuellen Thread verweisende Thread-ID mit der Thread-ID, auf die zugegriffen wird, übereinstimmt Wenn die Thread-ID unterschiedlich ist, versuchen Sie, die Sperre zu erhalten. Wenn die Erfassung erfolgreich ist, geben Sie den synchronisierten Block ein, um den Code auszuführen .

    Vorteile von voreingenommenen Sperren

    Voreingenommene Sperren sollen unnötige Sperrwechsel ohne Multi-Thread-Konkurrenz minimieren, da der Erwerb und die Freigabe von Sperren auf mehreren atomaren CAS-Anweisungen basieren und nur voreingenommene Sperren erforderlich sind. Es ist erforderlich, eine atomare CAS-Anweisung auszuführen einmal beim Ersetzen der Thread-ID.

    Mark Word Extended Knowledge: Speicherlayout

    In der virtuellen HotSpot-Maschine kann das Layout der im Speicher gespeicherten Objekte in die folgenden drei Bereiche unterteilt werden:

    • Objektkopf (Header)

    • Instanzdaten )

    • Ausgerichtete Polsterung (Padding)

    Der Objektkopf enthält außerdem:

    • Mark Word (Markierungsfeld): In diesem Bereich werden unsere Bias-Lock-Informationen gespeichert .

    • Klassenzeiger (Klassenobjektzeiger)

    Das Layout des Objekts im Speicher ist wie folgt:

    So implementieren Sie den Mechanismus zur Erweiterung der synchronisierten Sperre in Java

    In JDK 1.6 ist die voreingenommene Sperre standardmäßig aktiviert. Sie können die voreingenommene Sperre mit dem Befehl „-XX:-UseBiasedLocking=false“ deaktivieren.

    Leichte Sperre

    Der Zweck der Einführung einer leichten Sperre besteht darin, den Leistungsverbrauch zu reduzieren, der durch herkömmliche schwere Sperren unter Verwendung des Betriebssystems Mutex Lock (Mutex-Sperre) ohne Multithread-Konkurrenz verursacht wird. Wenn Sie Mutex Lock verwenden, führt jeder Vorgang zum Erlangen und Freigeben einer Sperre zu einem Wechsel zwischen Benutzermodus und Kernelmodus, was zu einem enormen Leistungsaufwand für das System führt.

    Wenn die Bias-Sperre deaktiviert ist oder mehrere Threads um die Bias-Sperre konkurrieren, wird die Bias-Sperre zu einer Lightweight-Sperre aktualisiert. Die Erfassung und Freigabe der Lightweight-Sperre erfolgt über CAS, und die Sperrenerfassung kann über a erfolgen Bestimmte Anzahl automatischer Sperren.

    Hinweise

    Es muss betont werden: Leichte Schlösser werden nicht als Ersatz für schwere Schlösser verwendet. Die ursprüngliche Absicht besteht darin, den Leistungsverbrauch zu reduzieren, der durch die Verwendung herkömmlicher schwerer Schlösser ohne Multithread-Konkurrenz verursacht wird. Das Szenario, an das sich Lightweight-Sperren anpassen, ist die Situation, in der Threads abwechselnd synchronisierte Blöcke ausführen. Wenn mehrere Threads gleichzeitig zugreifen, wird die Lightweight-Sperre zu einer Heavyweight-Sperre erweitert.

    Schwergewichtige Sperre

    synchronisiert verwendet den Monitor, um die Methodensynchronisation oder Codeblocksynchronisation zu implementieren. Die Monitorenter-Anweisung wird nach der Kompilierung in den Anfang des synchronisierten Codeblocks eingefügt Monitorexit wird am Ende der Methode und der Ausnahme eingefügt. Jedes Objekt ist mit einem Monitor verknüpft. Wenn ein Monitor gehalten wird, befindet er sich in einem gesperrten Zustand.

    Der folgende Sperrcode:

    public class SynchronizedToMonitorExample {
        public static void main(String[] args) {
            int count = 0;
            synchronized (SynchronizedToMonitorExample.class) {
                for (int i = 0; i < 10; i++) {
                    count++;
                }
            }
            System.out.println(count);
        }
    }

    Nachdem wir den obigen Code in Bytecode kompiliert haben, sieht sein Inhalt wie folgt aus:

    So implementieren Sie den Mechanismus zur Erweiterung der synchronisierten Sperre in Java

    Wie aus den obigen Ergebnissen ersichtlich ist, werden in der Hauptmethode mehrere Monitore eingegeben und eingegeben Es ist ersichtlich, dass die Synchronisierung auf der Monitor-Monitorsperre basiert und die Mutex-Sperre jedes Mal auf der Mutex-Sperre des Betriebssystems basiert Durch das Sperren wird zwischen Benutzermodus und Kernelmodus gewechselt, was den Leistungsaufwand des Systems erhöht.

    Das obige ist der detaillierte Inhalt vonSo implementieren Sie den Mechanismus zur Erweiterung der synchronisierten Sperre in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

    Stellungnahme:
    Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen