Dieser Artikel bietet Ihnen eine Einführung in die Verwendung des synchronisierten Schlüsselworts in Java (Codebeispiele). Ich hoffe, dass es einen gewissen Referenzwert hat es wird Ihnen hilfreich sein.
Bei der gleichzeitigen Programmierung spielt das synchronisierte Schlüsselwort eine häufige Rolle. Früher nannten wir das synchronisierte Schlüsselwort „Weight Lock“, aber „synchonized“ wurde in JDK1.6 optimiert und es wurden voreingenommene Sperren und leichte Sperren eingeführt. In diesem Artikel werden die Verwendung des synchronisierten Schlüsselworts sowie die Unterschiede und Implementierungsprinzipien von Bias-Sperren, leichten Sperren und schweren Sperren vorgestellt.
Sehen wir uns zunächst die vier Verwendungsmöglichkeiten des synchronisierten Schlüsselworts an.
1. Gewöhnliche Methoden ändern
private synchronized void synMethod(){ }
In dieser Verwendung Objekt Instanz einer synchronisierten Sperre.
2. Statische Methoden ändern
private static synchronized void synMethod(){ }
synchronisiert In diesem Fall ist die Sperre das aktuelle Klassenobjekt.
3. Synchroner Methodenblock
private void synMethod1(){ synchronized(this){ } } private void synMethod2(){ synchronized(ThreadTest.class){ } }
Objektinstanz in synMethod1 sperren; das aktuelle Klassenobjekt.
Einführung in das Sperrprinzip
Bevor wir das Sperrprinzip einführen, lernen wir zunächst den Java-Objektheader Mark Word kennen, der 32-Bit verwendet als Beispiel.
Sperrstatus |
25 Bit |
4bit |
1bit |
2bit |
||
|
23bit |
2bit |
Ob es in Richtung Sperre voreingenommen ist |
Sperrflagge |
||
Leichtes Schloss |
Zeiger auf den Sperrdatensatz im Stapel |
0 |
||||
Schwergewichtsschloss |
Zeiger auf Mutex (Schwergewichtssperre) |
10 |
||||
GCMarkieren |
Leer |
11 |
||||
Bias-Sperre |
ThreadID |
Epoche | Alter der Objektgenerierung |
1 |
01 |
|
Lockless |
HashCode des Objekts | Alter der Objektgenerierung |
0 |
01 |
Die obige Tabelle beschreibt die im Objektheader gespeicherten Informationen, wenn sich das Objekt in jedem Sperrstatus befindet.
1. Voreingenommene Sperre
Wenn in der tatsächlichen Umgebung ein Thread auf einen synchronisierten Block zugreift und kein anderer Thread um die Sperre konkurriert, und Derselbe Thread erhält die Sperre mehrmals, d. h. ein einzelner Thread führt den Synchronisationscode aus. Wenn der Thread in diesem Fall jedes Mal blockiert wird, bedeutet dies eine Verschwendung von CPU-Leistung. In diesem Fall wird das Konzept der vorgespannten Verriegelung eingeführt.
Zugriff auf synchronisierten Codeblock
Bestimmen Sie, ob die im Objektheader Mark Word gespeicherte Thread-ID auf den aktuellen Thread verweist. Wenn dies der Fall ist, bedeutet dies, dass die aktuelle Sperre nicht erforderlich ist, und führen Sie die Synchronisierung nicht direkt aus Code
Wenn nicht, versuchen Sie, den CAS-Algorithmus zu verwenden, um die Thread-ID im Objektheader zu aktualisieren.
Erhält erfolgreich die Sperre und führt den Synchronisierungscode aus. Wenn die Aktualisierung fehlschlägt, bedeutet dies, dass eine Sperrenkonkurrenz vorliegt. Warten Sie auf den globalen Sicherheitspunkt, halten Sie den Thread an, der die voreingenommene Sperre besitzt, und entscheiden Sie sich dafür, die voreingenommene Sperre auf eine leichte Sperre zu aktualisieren oder sie gemäß dem Sperrflag in auf keine Sperre zu setzen Objekt-Header.
Sie können -XX:-userBiasedLocking=false verwenden, um die voreingenommene JVM-Sperroptimierung zu deaktivieren und die Lightweight-Sperre standardmäßig direkt einzugeben.
2. Leichte Sperre
Zugriff auf den Synchronisierungscodeblock Erstellen Sie zunächst einen Sperrdatensatzbereich (Lock Record) im Thread-Stapel des aktuellen Threads.
Kopieren Sie den Objektheader Mark Word in den Sperrdatensatz.
Verwenden Sie CAS, um zu versuchen, den Thread-Zeiger im Objektheader Mark Word auf einen Zeiger auf den aktuellen Thread zu aktualisieren
Wenn die Aktualisierung erfolgt Erfolgreich erhalten Sie ein leichtes Schloss.
Aktualisierung fehlgeschlagen. Überprüfen Sie, ob der Zeiger in Mark Word auf den aktuellen Thread zeigt.
Wenn ja, bedeutet dies einen Wiedereintritt in die Sperre. Synchronisierten Codeblock ausführen
Wenn nicht, bedeutet dies, dass derzeit Konkurrenz besteht. Leichte Schlösser müssen zu Gewichtsschlössern erweitert werden.
3. Gewichtssperre
Die Gewichtssperre wird auf Basis des Objektmonitors (Monitor) implementiert.
Wenn ein Thread Synchronisationscode ausführt, muss er eine Monitor.enter-Anweisung aufrufen. Rufen Sie nach Beendigung der Ausführung die Anweisung „Monitor.exit“ auf. Hier ist ersichtlich, dass der Monitor exklusiv ist. Es kann jeweils nur ein Thread erfolgreich eingegeben werden und andere Threads können nur in der Warteschlange blockiert werden. Daher ist der Betrieb dieser Gewichtssperre sehr teuer.
Das obige ist der detaillierte Inhalt vonEinführung in die Verwendung des synchronisierten Schlüsselworts in Java (Codebeispiel). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!