1. Synchronisierter Sperrwiedereintritt
1.1 Einführung
Das Schlüsselwort synchronisiert hat die Funktion der Wiedereintrittsfunktion der Sperre. Das heißt, wenn ein Thread bei Verwendung von synchronisiert eine Objektsperre erhält, kann er die Objektsperre erneut erhalten, wenn er die Objektsperre erneut anfordert. Dies zeigt, dass beim Aufruf anderer synchronisierter Methoden/Blöcke dieser Klasse innerhalb einer synchronisierten Methode/eines synchronisierten Blocks die Sperre immer erhalten werden kann.
Zum Beispiel:
public class Service1 { public synchronized void method1(){ System.out.println("method1"); method2(); } public synchronized void method2(){ System.out.println("method2"); method3(); } public synchronized void method3(){ System.out.println("method3"); } }
Das Laufergebnis ist wie folgt:
☹ Als ich dieses Ergebnis sah, war ich verwirrt, warum? Ist bewiesen, dass die Sperre wiedereintretend ist?
➤ Das Konzept der „Wiedereintrittssperre“ besteht darin, dass Sie Ihre eigene interne Sperre erneut erwerben können. Zu diesem Zeitpunkt wurde die Objektsperre nicht aufgehoben Erfassen Sie es erneut. Es ist immer noch möglich, die Sperre dieses Objekts zu erhalten. Wenn die Sperre nicht wiedereintrittsfähig ist, tritt ein Deadlock auf.
➤ Die größte Rolle der „Wiedereintrittssperre“ besteht darin, Deadlocks zu vermeiden
1.2-Analyse
Uns als Sie wissen, dass im Programm die Sperre für den Synchronisationsmonitor nicht explizit aufgehoben werden kann, aber die Sperre wird in den folgenden Situationen aufgehoben:
① Wird freigegeben, wenn die Ausführung der Synchronisationsmethode und des Codeblocks des aktuellen Threads endet
② Wird freigegeben, wenn der aktuelle Thread auf eine Unterbrechung oder Rückkehr stößt, um den Codeblock oder die Methode in einer synchronisierten Methode oder einem synchronisierten Codeblock zu beenden
③ Wird freigegeben, wenn ein nicht behandelter Fehler oder eine Ausnahme auftritt, die ein abnormales Ende verursacht
④ Das Programm führt die Synchronisierung aus Objektwartemethode, der aktuelle Thread hält an und gibt die Sperre frei
Wenn der Thread im obigen Programm dann die Synchronisationsmethode Methode1 betritt, erhält er die Objektsperre von Service1, aber wenn er Methode1 ausführt, erhält er die Synchronisationsmethode Methode2 wird normalerweise aufgerufen. In diesem Fall müssen Sie beim Ausführen der Synchronisationsmethode Methode2 auch die Objektsperre erhalten. Gemäß den oben genannten Sperrfreigabebedingungen wurde die Objektsperre von Methode1 zu diesem Zeitpunkt jedoch noch nicht freigegeben , was zu einem Deadlock führt und Methode2 nicht weiter ausgeführt werden kann. Den Ausführungsergebnissen des obigen Codes nach zu urteilen, können Methode2 und Methode3 jedoch normal ausgeführt werden, was bedeutet, dass beim Aufrufen anderer synchronisierter Methoden oder Codeblöcke dieser Klasse innerhalb einer synchronisierten Methode oder eines Codeblocks immer erhalten werden kann das Schloss .
1.3 Eltern-Kind-Vererbung
Wiedereintretende Sperren werden in der Umgebung der Eltern-Kind-Klassenvererbung unterstützt. Der Beispielcode lautet wie folgt:
public class MyThread extends Thread { @Override public void run(){ Service1 service1 = new Service1(); service1.method1(); } public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); } }
public class Service2 { public int i = 10; public synchronized void mainMethod(){ i--; System.out.println("main print i="+i); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } }
public class Service3 extends Service2 { public synchronized void subMethod(){ try{ while (i>0){ i--; System.out.println("sub print i= "+i); Thread.sleep(100); this.mainMethod(); } }catch (InterruptedException e){ e.printStackTrace(); } } }
Die laufenden Ergebnisse lauten wie folgt:
Dieses Programm zeigt, dass die Unterklasse die Synchronisationsmethode der übergeordneten Klasse vollständig aufrufen kann, wenn eine Vererbungsbeziehung zwischen übergeordneten und untergeordneten Klassen besteht Klasse durch „Reentrant Lock“.
2. Wenn eine Ausnahme auftritt, wird die Sperre automatisch aufgehoben.
Wenn eine Ausnahme im von einem Thread ausgeführten Code auftritt, wird die Sperre aufgehoben Es wird automatisch freigegeben.
Der Bestätigungscode lautet wie folgt:
public class MyThread extends Thread { @Override public void run(){ Service3 service3 = new Service3(); service3.subMethod(); } public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); } }
public class Service4 { public synchronized void testMethod(){ if(Thread.currentThread().getName().equals("a")){ System.out.println("ThreadName= "+Thread.currentThread().getName()+" run beginTime="+System.currentTimeMillis()); int i=1; while (i == 1){ if((""+Math.random()).substring(0,8).equals("0.123456")){ System.out.println("ThreadName= "+Thread.currentThread().getName()+" run exceptionTime="+System.currentTimeMillis()); //Integer.parseInt("a"); } } }else{ System.out.println("Thread B run time= "+System.currentTimeMillis()); } } }
public class ThreadA extends Thread{ private Service4 service4; public ThreadA(Service4 service4){ this.service4 = service4; } @Override public void run(){ service4.testMethod(); } }
public class ThreadB extends Thread{ private Service4 service4; public ThreadB(Service4 service4){ this.service4 = service4; } @Override public void run(){ service4.testMethod(); } }
Beachten Sie, dass in der Service4-Klasse zu diesem Zeitpunkt Integer.parseInt(“a”); kommentiert ist und die laufenden Ergebnisse sind wie folgt:
Da Thread a keinen Fehler hat, während (true) sich Thread a zu diesem Zeitpunkt in einer Endlosschleife befindet, ist die Sperre immer von a belegt, Thread b kann die Sperre nicht erhalten. Das heißt, Thread b kann nicht ausgeführt werden.
Kommentieren Sie Integer.parseInt(“a”); in der Service4-Klasse aus, und das Ausführungsergebnis ist wie folgt:
Wenn an In Thread a tritt ein Fehler auf, Thread b erhält die Sperre und führt sie aus. Es ist ersichtlich, dass die Sperre automatisch aufgehoben wird, wenn in der Methode eine Ausnahme auftritt.
3. Beliebiges Objekt als Monitor verwenden
Java unterstützt die Funktion, „jedes Objekt“ als „Objektmonitor“ zu synchronisieren. Die meisten dieser „beliebigen Objekte“ sind Instanzvariablen und Methodenparameter, und das Format ist ein synchronisierter (nicht dieses Objekt x) synchronisierter Codeblock.Der Beispielcode lautet wie folgt:
public class Main { public static void main(String[] args) { try { Service4 service4 = new Service4(); ThreadA a = new ThreadA(service4); a.setName("a"); a.start(); Thread.sleep(500); ThreadB b = new ThreadB(service4); b.setName("b"); b.start(); } catch (InterruptedException e) { e.printStackTrace(); } } }
Das Sperren von Nicht-diesem-Objekten hat gewisse Vorteile: Wenn es viele synchronisierte Methoden in einem gibt Die Synchronisierung der Klasse kann zwar erreicht werden, wird jedoch blockiert, sodass die Betriebseffizienz beeinträchtigt wird. Wenn jedoch ein synchronisierter Codeblock zum Sperren eines Nicht-dieses-Objekts verwendet wird, werden das Programm und die Synchronisationsmethode im synchronisierten (nicht diesem) Code zugeordnet Der Block ist asynchron und andere Sperren sind nicht zulässig. Der Kampf um diese Sperre kann die Betriebseffizienz erheblich verbessern.
4. Die Synchronisation hat keine Vererbung
Die Synchronisationsmethode der übergeordneten Klasse funktioniert nicht, wenn sie in der Unterklasse neu geschrieben wird, ohne das Synchronisationsschlüsselwort hinzuzufügen . Synchron, Sie müssen also das synchronisierte Schlüsselwort zur Methode der Unterklasse hinzufügen.
Empfohlenes Lernen: Java-Video-Tutorial
Das obige ist der detaillierte Inhalt vonWerfen wir einen Blick auf die 4 Funktionen von Synchronized. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!