Das synchronisierte Schlüsselwort stellt dar, dass diese Methode gesperrt ist. Es entspricht unabhängig von welchem Thread (z. B. Thread A), wenn Sie diese Methode ausführen, müssen Sie überprüfen, ob andere Threads B (oder C, D usw.) diese Methode (oder andere Synchronisationsmethoden dieser Klasse) verwenden. Wenn ja, warten Sie auf Thread B (oder C, D), bei dem die synchronisierte Methode verwendet wird, um diese Methode auszuführen, bevor diese Methode ausgeführt wird. Wenn nicht, sperren Sie den Anrufer und führen Sie ihn direkt aus. Es enthält zwei Verwendungen: die synchronisierte Methode und den synchronisierten Block.
Der Multi-Thread-Synchronisationsmechanismus sperrt Ressourcen, sodass gleichzeitig nur ein Thread arbeiten kann und die Synchronisation die Probleme lösen kann, die auftreten können, wenn mehrere Fäden gleichzeitig zugreifen.
Der Synchronisationsmechanismus kann mit dem synchronisierten Schlüsselwort implementiert werden.
Wenn das synchronisierte Schlüsselwort eine Methode modifiziert, wird die Methode als Synchronisationsmethode bezeichnet.
Wenn die synchronisierte Methode ausgeführt wird oder eine Ausnahme auftritt, wird die Sperre automatisch freigegeben.
Das Folgende ist ein Beispiel zur Analyse der Verwendung synchronisierter Schlüsselwörter.
1. Verwendungszwecke von synchronisierten Schlüsselwörtern
Beispielprogramm 1
public class threadTest {public static void main (String [] args) {Beispiel für Beispiel = neuer Beispiel (); Thread T1 = neuer Thread1 (Beispiel); Thread T2 = neuer Thread1 (Beispiel); t1.start (); t2.Start (); }} Klasse Beispiel {public synchronisierte void execute () {für (int i = 0; i <10; ++ i) {try {thread.sleep (500); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Hallo:" + i); }}} Klasse Thread1 erweitert Thread {privates Beispiel; public thread1 (Beispiel Beispiel) {this.example = Beispiel; } @Override public void run () {example.execute (); }} Unabhängig davon, ob das synchronisierte Schlüsselwort in der Methode execute () vorbereitet wird, ist die Ausführungsergebnisse dieses Beispielprogramms sehr unterschiedlich.
Wenn das synchronisierte Schlüsselwort nicht hinzugefügt wird, führen die beiden Threads gleichzeitig die Ausführungsmethode aus, und die Ausgabe besteht aus zwei Gruppen von gleichzeitiger.
Wenn das synchronisierte Schlüsselwort hinzugefügt wird, wird zuerst ein Satz von 0 bis 9 ausgegeben, und dann wird der nächste Satz ausgegeben, der angibt, dass die beiden Threads nacheinander ausgeführt werden.
2. Multi-Threading-Situation mehrerer Methoden
Ändern Sie das Programm und fügen Sie eine andere Methode aus, um2 () in die Beispielklasse auszuführen.
Schreiben Sie dann einen Thread -Klasse -Thread2. Die Run () -Methode in Thread2 wird execute2 () ausgeführt. Beide Methoden in der Beispielklasse werden durch das synchronisierte Schlüsselwort geändert.
Beispielprogramm 2
public class threadTest {public static void main (String [] args) {Beispiel für Beispiel = neuer Beispiel (); Thread T1 = neuer Thread1 (Beispiel); Thread T2 = neuer Thread2 (Beispiel); t1.start (); t2.Start (); }} Klasse Beispiel {public synchronisierte void execute () {für (int i = 0; i <20; ++ i) {try {thread.sleep ((lang) math.random () * 1000); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Hallo:" + i); }} public Synchronized void execute2 () {für (int i = 0; i <20; ++ i) {try {thread.sleep ((lang) math.random () * 1000); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Welt:" + i); }}} Klasse Thread1 erweitert Thread {privates Beispiel; public thread1 (Beispiel Beispiel) {this.example = Beispiel; } @Override public void run () {example.execute (); }} Klasse Thread2 erweitert Thread {private Beispiel; public thread2 (Beispiel Beispiel) {this.example = Beispiel; } @Override public void run () {example.execute2 (); }} Wenn das synchronisierte Schlüsselwort entfernt wird, werden die beiden Methoden gleichzeitig ausgeführt und haben keinen gegenseitigen Einfluss.
Aber wie in der Beispiel -Unterroutine auch zwei Methoden geschrieben:
Das Ausführungsergebnis ist immer die Ausgabe eines Threads und dann die Ausführung eines anderen Threads.
veranschaulichen:
Wenn ein Objekt mehrere synchronisierte Methoden hat und ein Thread zu einem bestimmten Zeitpunkt eine synchronisierte Methode eingegeben hat, können andere Threads nicht auf synchronisierte Methoden des Objekts zugreifen, bevor die Methode ausgeführt wird.
abschließend:
Wenn das synchronisierte Schlüsselwort eine Methode modifiziert, wird die Methode als Synchronisationsmethode bezeichnet.
Jedes Objekt in Java hat ein Schloss oder einen Monitor. Wenn ein Thread auf die synchronisierte Methode eines Objekts zugreift, ist das Objekt gesperrt und kein anderer Thread kann auf die synchronisierte Methode des Objekts zugreifen (hier bezieht sich auf alle Synchronisationsmethoden, nicht nur auf dieselbe Methode). Erst wenn der vorherige Thread die Ausführungsmethode abschließt (oder eine Ausnahme ausgelöst), wird die Sperre des Objekts freigegeben, sodass andere Threads erneut auf die synchronisierte Methode des Objekts zugreifen können.
Beachten Sie, dass das Objekt zu diesem Zeitpunkt gesperrt ist. Wenn es sich um ein anderes Objekt handelt, gibt es keine Restriktionsbeziehung zwischen den Objekten.
Beim Versuch, ein zweites Threadobjekt im Code zu konstruieren, wird ein neues Beispielobjekt übergeben, dann besteht keine Einschränkung zwischen der Ausführung der beiden Threads.
3. Betrachten Sie statische Synchronisationsmethoden
Wenn eine synchronisierte Schlüsselwort-modifizierte Methode ebenfalls durch statische modifiziert wird, wurde zuvor gesagt, dass eine nicht statische Synchronisationsmethode das Objekt sperrte, aber die statische Methode gehört nicht zum Objekt, sondern zur Klasse und sperrt das Klassenobjekt der Klasse, in dem sich diese Methode befindet.
Unabhängig davon, wie viele Objekte eine Klasse generiert, entsprechen sie demselben Klassenobjekt.
Beispielprogramm 3
public class threadTest {public static void main (String [] args) {Beispiel für Beispiel = neuer Beispiel (); Thread T1 = neuer Thread1 (Beispiel); // Auch wenn hier verschiedene Objekte übergeben werden, erlaubt die statische Methode -Synchronisation nicht mehr, dass mehrere Threads gleichzeitig ausgeführt werden können. Beispiel = neuer Beispiel (); Thread T2 = neuer Thread2 (Beispiel); t1.start (); t2.Start (); }} Klasse Beispiel {public synchronisierte statische void execute () {für (int i = 0; i <20; ++ i) {try {thread.sleep ((lang) math.random () * 1000); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Hallo:" + i); }} public synchronisierte statische void execute2 () {für (int i = 0; i <20; ++ i) {try {thread.sleep ((lang) math.random () * 1000); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Welt:" + i); }}} Klasse Thread1 erweitert Thread {privates Beispiel; public thread1 (Beispiel Beispiel) {this.example = Beispiel; } @Override public void run () {example.execute (); }} Klasse Thread2 erweitert Thread {private Beispiel; public thread2 (Beispiel Beispiel) {this.example = Beispiel; } @Override public void run () {example.execute2 (); }} Wenn es sich also um eine statische Methode handelt (execute () und execute2 () haben beide statische Schlüsselwörter hinzugefügt), selbst wenn verschiedene Beispielobjekte an zwei Threads übergeben werden, werden die beiden Threads immer noch voneinander eingeschränkt. Man muss zuerst ausgeführt werden und dann der nächste.
abschließend:
Wenn eine synchronisierte Methode statisch ist und ein Thread auf die Methode zugreift, sperrt es nicht das Objekt, in dem sich die synchronisierte Methode befindet, sondern das Klassenobjekt, das der Klasse entspricht, in der sich die synchronisierte Methode befindet. In Java entsprechen diese Objekte, egal wie viele Objekte eine Klasse hat, einem einzigartigen Klassenobjekt. Wenn ein Thread auf zwei statische und synchronisierte Methoden von zwei Objekten derselben Klasse zugreift, ist seine Ausführungsreihenfolge auch sequentiell, dh ein Thread wird zuerst die Methode ausführen, und der andere Thread startet nach Abschluss der Ausführung.
4. Synchronisierter Block
Synchronisierte Blockschreibmethode:
synchronisiert (Objekt) {} Dies bedeutet, dass der Thread das Objektobjekt sperrt, wenn es ausgeführt wird. (Beachten Sie, dass dieses Objekt ein Objekt jeder Klasse sein kann oder Sie dieses Schlüsselwort verwenden können.)
Auf diese Weise können Sie das gesperrte Objekt selbst angeben.
Beispielprogramm 4
public class threadTest {public static void main (String [] args) {Beispiel für Beispiel = neuer Beispiel (); Thread T1 = neuer Thread1 (Beispiel); Thread T2 = neuer Thread2 (Beispiel); t1.start (); t2.Start (); }} Klasse Beispiel {private Object Object = new Object (); public void execute () {synchronized (Objekt) {für (int i = 0; i <20; ++ i) {try {thread.sleep ((lang) math.random () * 1000); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Hallo:" + i); }}} public void execute2 () {synchronized (Object) {für (int i = 0; i <20; ++ i) {try {thread.sleep ((lang) math.random () * 1000); } catch (interruptedException e) {e.printstacktrace (); } System.out.println ("Welt:" + i); }}}}} Klasse Thread1 erweitert Thread {privates Beispiel; public thread1 (Beispiel Beispiel) {this.example = Beispiel; } @Override public void run () {example.execute (); }} Klasse Thread2 erweitert Thread {private Beispiel; public thread2 (Beispiel Beispiel) {this.example = Beispiel; } @Override public void run () {example.execute2 (); }} Der Effekt, der mit dem Beispielprogramm 4 erzielt wird, entspricht dem von Beispielprogramm 2. Beide Threads werden eher nacheinander als gleichzeitig ausgeführt. Wenn ein Thread ausgeführt wird, ist das Objektobjekt gesperrt und der andere Thread kann den entsprechenden Block nicht ausführen.
Die synchronisierte Methode entspricht tatsächlich dem Umwickeln aller Anweisungen in der Methode mit einem synchronisierten Block und über das Bestehen dieses Schlüsselworts in den Klammern des synchronisierten Blocks. Wenn es sich um eine statische Methode handelt, muss das Klassenobjekt natürlich gesperrt werden.
Vielleicht beinhaltet nur wenige Codezeilen in einer Methode Thread -Synchronisationsprobleme, sodass der synchronisierte Block den Zugriff mehrerer Threads körniger als die synchronisierte Methode steuert. Nur auf den Inhalt im synchronisierten Block kann nicht gleichzeitig von mehreren Threads zugegriffen werden, und andere Anweisungen in der Methode können weiterhin gleichzeitig von mehreren Threads (einschließlich vor und nach dem synchronisierten Block) zugegriffen werden.
Hinweis: Die durch synchronisierten Daten geschützt sollten privat sein.
abschließend:
Die synchronisierte Methode ist eine grobkörnige gleichzeitige Kontrolle. Zu einem bestimmten Zeitpunkt kann nur ein Thread die synchronisierte Methode ausführen.
Der synchronisierte Block ist eine feinkörnige Parallelitätskontrolle, die den Code nur im Block synchronisiert. Andere Codes, die sich in der Methode befinden und außer synchronisierten Blöcken, können gleichzeitig von mehreren Threads zugegriffen werden.