0. In Bezug auf die Threadsynchronisation (1) Warum müssen wir Multithreading synchronisieren?
Die Thread -Synchronisation bezieht sich darauf, dass mehrere laufende Threads gut zusammenarbeiten können, damit mehrere Threads die Ressourcen nach Bedarf angemessen besetzen und freigeben können. Wir verwenden Synchronisationscodeblöcke und Synchronisationsmethoden in Java, um dieses Ziel zu erreichen. Lösen Sie beispielsweise das Problem der multi-thread-nicht-fixierten Ordenausführung:
public class twotHhreadtest {public static void main (String [] args) {Thread th1 = new MyThread1 (); Thread Th2 = neuer mythread2 (); Th1.Start (); th2.Start (); }} class mythread2 erweitert Thread {@Override public void run () {für (int i = 0; i <10; i ++) System. out.println ("Thread 1 Zähler:"+i); }} class mythread1 erweitert Thread {@Override public void run () {für (int i = 0; i <10; i ++) System. out.println ("Thread 1 Zähler:"+i); }} class mythread1 erweitert Thread {@Override public void run () {für (int i = 0; i <10; i ++) System. out.println ("Thread 2 Zähler:"+i); }}Das Ergebnis einer Multi-Thread-Ausführung in diesem Zustand besteht darin, die Ausführung nach Belieben zufällig einzufügen, was vollständig von der Thread-Planung des JVM abhängt. In vielen Fällen, in denen eine ordnungsgemäße Ausführung erforderlich ist, ist dieser zufällige Ausführungszustand offensichtlich ungeeignet.
public class threadtest {public static void main (String [] args) {mythead thread = new myThread (); Thread Th1 = neuer Thread (Thread); Thread Th2 = neuer Thread (Thread); Th1.Start (); th2.Start (); }} Klasse MyThread implementiert runnable {@Override public synchronisierte void run () {für (int i = 0; i <10; i ++) System. out.println (Thread. currentThread (). getName ()+"counter:"+i); }}Nach Verwendung der Synchronisationsmethode können wir den Thread steuern, um das Ausführungskörperobjekt ausschließlich zu besetzen. Auf diese Weise kann der Thread während des Ausführungsprozesses die Aufgaben in der Ausführungsbehörde gleichzeitig ausführen und den Schließstatus verlassen. Das JVM schickt dann einen weiteren Thread, um die Aufgaben gleichzeitig in der Ausführungsbehörde auszuführen.
(2) Das Paradigma für die Erstellung und das Laufen von Threads:
In der Vergangenheit hatten wir auch unser eigenes Programmierparadigma für die Erstellung von Threads und das Laufen. Im Allgemeinen haben wir eine Ausführungsklasse definiert, um die Run () -Methode neu zu schreiben, aber diese Methode setzt die Ausführungsbehörde und die ausgeführten Aufgaben zusammen, was nicht für die Entkopplung aus der Sicht des Software -Engineering förderlich ist. Die Ausführung eines Threads bedeutet, dass ein Thread eine Aufgabe eines Objekts über das Ausführungsobjekt ausführt. Aus dieser Perspektive kann die Trennung des Verschreibers der Aufgabe von der Ausführungsklasse die verschiedenen Rollen der Programmierung von Multi-Thread-Programmierungen klarstellen und somit eine gute Entkopplung erhalten. Das Folgende ist das Programmierparadigma für die Erstellung und Ausführung von Threads:
public class formalThreadClass {public static void main (String [] args) {Thread thread = neuer Thread (neuer Myrunnable ()); Thread.Start (); }} Klasse Myrunnable Geräte runnable {mytask mytask = new mytask (); @Override public void run () {mytask.dotask (); }} Klasse mytask {public void dotask () {System. out.println ("Dies ist echte Aufgabe"); }}
1. Synchronisierter Prinzip
In Java hat jedes Objekt eine Synchronisationsschloss. Dies bedeutet auch, dass das Synchronisationsschloss auf dem Objekt vorhanden ist.
Wenn wir die synchronisierte Methode eines Objekts nennen, erwerben wir die Synchronisationsschloss des Objekts. Beispielsweise erfasst synchronisierte (OBJ) die Synchronisationsschloss des "OBJ -Objekts".
Der Zugriff auf Synchronisationsperren durch verschiedene Threads schließt sich gegenseitig aus. Mit anderen Worten, zu einem bestimmten Zeitpunkt kann die Synchronisationsschloss des Objekts nur durch einen Thread erhalten werden! Durch Synchronisationssperrs können wir in mehreren Threads einen sich gegenseitig ausschließenden Zugriff auf "Objekte/Methoden" erreichen. Zum Beispiel gibt es jetzt zwei Threads A und Thread B, die beide auf das "Synchronen Lock of Object OBJ" zugreifen. Nehmen wir an, dass Faden A irgendwann die "Obj -Synchronisationsschloss" erwerben und einige Operationen durchführen. Zu diesem Zeitpunkt versucht Thread B auch, das "Obj's Synchronization Lock" zu erwerben - Thread B wird nicht erwerben, es muss warten, bis Thread A die "Obj's Synchronisation Lock" veröffentlicht und nur ausgeführt werden kann.
2. Synchronisierte Grundregeln
Wir fassen die grundlegenden Regeln von Synchron in die folgenden 3 zusammen und veranschaulichen sie anhand von Beispielen.
Artikel 1: Wenn ein Thread auf die "synchronisierte Methode" oder "synchronisierten Codeblock" von "einem bestimmten Objekt" zugreift, werden andere Threads vom Zugriff auf die "synchronisierte Methode" oder "Synchronisierter Codeblock" des "Objekts" blockiert.
Artikel 2: Wenn ein Thread auf die "synchronisierte Methode" oder "synchronisierten Codeblock" von "einem bestimmten Objekt" zugreift, können andere Threads weiterhin auf den asynchronisierten Codeblock von "dieses Objekt" zugreifen.
Artikel 3: Wenn ein Thread auf die "synchronisierte Methode" oder "synchronisierten Codeblock" von "einem bestimmten Objekt" zugreift, werden andere Threads aus dem Zugriff auf andere "synchronisierte Methoden" oder "Synchronisierter Codeblock" von "The Object" blockiert.
(1) Artikel 1:
Wenn ein Thread auf die "synchronisierte Methode" oder "synchronisierte Codeblock" von "einem bestimmten Objekt" zugreift, werden andere Threads vom Zugriff auf die "synchronisierte Methode" oder "synchronisierter Codeblock" des "Objekts" blockiert. Nachfolgend finden Sie das Demonstrationsprogramm, das "Synchronisierter Codeblock" entspricht.
Klasse Myrunable Implements Runnable {@Override public void run () {synchronized (this) {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName () + "Loop" + i); }} catch (InterruptedException IE) {}}}} öffentliche Klasse Demo1_1 {public static void main (String [] args) {runnable Demo = new Myrunable (); // Erstellen Sie einen neuen "Runnable -Objekt" -Thread t1 = neuer Thread (Demo, "T1"); // Erstellen Sie einen neuen "Thread T1", T1 basiert auf dem Runnable -Objekt -Thread t2 = neuer Thread (Demo, "T2"); // Erstellen Sie ein neues "Thread T2", T2 basiert auf dem Runnable -Objekt t1.start (); // Start "Thread t1" t2.start (); // "Thread T2"}} starten Auslaufergebnisse:
T1 Loop 0T1 Loop 1T1 Loop 2T1 Loop 3T1 Loop 4T2 Loop 0T2 Loop 1T2 Loop 2T2 Loop 3T2 Loop 4
Das Ergebnis zeigt, dass in der Run () -Methode eine "synchronisierte (dieser) Codeblocke" vorhanden ist, und T1 und T2 sind Threads, die basierend auf dem "Demo" -Runnable -Objekt erstellt wurden. Dies bedeutet, dass wir dies als "Demo -Runnable -Objekt" betrachten können. Daher teilen sich Threads T1 und T2 "Synchronen Schloss des Demo -Objekts". Wenn ein Thread ausgeführt wird, muss ein anderer Thread warten, bis der "Auslauf -Thread" die "Demo -Synchronisationssperrung" freigibt, bevor er ausgeführt werden kann.
Wenn Sie bestätigen, haben Sie dieses Problem herausgefunden. Dann ändern wir den obigen Code und führen ihn dann aus, um zu sehen, wie das Ergebnis ist, und feststellen, ob Sie verwirrt sind. Der geänderte Quellcode lautet wie folgt:
Klasse myThread erweitert Thread {public myThread (String name) {Super (name); } @Override public void run () {synchronized (this) {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName () + "Loop" + i); }} catch (InterruptedException IE) {}}}} öffentliche Klasse Demo1_2 {public static void main (String [] args) {Thread t1 = new MyThread ("t1"); // Neue "Thread T1" Thread T2 = New MyThread ("T2"); // neue "Thread T2" t1.start () erstellen; // Start "Thread t1" t2.start (); // "Thread T2"}} starten Code Beschreibung: Wenn wir Demo1_2 und Demo1_1 vergleichen, fanden wir, dass die MyThread -Klasse in Demo1_2 direkt aus Thread geerbt wird und T1 und T2 beide MyThread Child -Threads sind.
Glücklicherweise wird die "run () -Methode von Demo1_2" auch als synchronisiert (this) genannt, ebenso wie die "Run () -Methode von Demo1_1" auch als synchronisiert (this) genannt!
Ist also der Ausführungsprozess von Demo1_2 wie demo1_1? Auslaufergebnisse:
T1 Loop 0T2 Loop 0T1 Loop 1T2 Loop 1T1 Loop 2T2 Loop 2T1 Loop 3T2 Loop 3T1 Loop 4T2 Loop 4
Ergebnisse Beschreibung:
Wenn dieses Ergebnis Sie überhaupt nicht überrascht, dann glaube ich, dass Sie ein tieferes Verständnis der synchronisierten und dies haben. Andernfalls lesen Sie die Analyse hier weiter.
Dies in synchronisiertem (dies) bezieht sich auf das "aktuelle Klassenobjekt", dh das aktuelle Objekt, das der Klasse entspricht, in der sich synchronisiert (dieses) befindet. Sein Zweck ist es, die "synchrone Schloss des aktuellen Objekts" zu erhalten.
Für Demo1_2 repräsentiert dies in synchronisiertem (dies) das MyThread -Objekt, während T1 und T2 zwei verschiedene MyThread -Objekte sind. Wenn T1 und T2 synchronisiert (dies) ausführen, erwerben sie daher die Synchronisationssperrungen verschiedener Objekte. Für das Demo1_1 -Paar repräsentiert dies in synchronisiertem (this) das myrelbare Objekt; T1 und T2 teilen sich ein myrtiges Objekt. Daher erfasst ein Thread die Synchronisationsschloss des Objekts, wodurch ein weiterer Thread wartet.
(2) Artikel 2:
Wenn ein Thread auf die "synchronisierte Methode" oder "synchronisierte Codeblock" von "einem bestimmten Objekt" zugreift, können andere Threads weiterhin auf den asynchronisierten Codeblock von "dieses Objekt" zugreifen.
Nachfolgend finden Sie das Demonstrationsprogramm, das "Synchronisierter Codeblock" entspricht.
Klasse count {// Methoden, die synchronisierte Synchronisation blockieren, blockiert public void synmeThod () {synchronisiert (this) {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // Sleep for 100ms System.out.println (Thread.currentThread (). GetName () + "Synmethod Loop" + i); }} catch (InterruptedException IE) {}}} // Asynchronous method public void nonsynMethod () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); System.out.println (Thread.currentThread (). GetName () + "NonSynMethod Loop" + i); }} catch (InterruptedException IE) {}}} öffentliche Klasse Demo2 {public static void main (String [] args) {endgültig count = new Count (); // Neue T1 erstellen, T1 ruft die SynMethod () -Methode von "count Object" -Thread t1 = neuer Thread (new Runnable () {@Override public void run () {count.ynmethod ();}}, "t1") auf; // Erstellen Sie einen neuen T2, T2 ruft die nichtsynMethod () -Methode des "count -Objekt" -Threads t2 = neuer Thread (neu Runnable () {@Override public void run () {count.nonsynMethod ();}}, "t2") auf. t1.start (); // starten t1 t2.start (); // T2}} starten Auslaufergebnisse:
t1
Ergebnisse Beschreibung:
Zwei neue Kinderfäden T1 und T2 werden im Hauptfaden erstellt. T1 ruft die Synmethod () -Methode des Zählobjekts auf, das Synchronisationsblöcke enthält. T2 ruft die NonsynmeThod () -Methode des Zählobjekts auf, die keine Synchronisationsmethode darstellt. Wenn T1 ausgeführt wird, wird zwar synchronisiert (dies) aufgerufen, um das "Zählsynchronisationsschloss" zu erhalten; Es blockiert T2 nicht, da T2 das "Count" -Synchronisationsschloss nicht verwendet.
(3) Artikel 3:
Wenn ein Thread auf die "synchronisierte Methode" oder "synchronisierten Codeblock" von "einem bestimmten Objekt" zugreift, zugänglich wird auf andere "synchronisierte Methoden" oder "synchronisierter Codeblock" des "Objekts" zugegriffen.
Wir werden auch den nichtsynmeThod () -Methodenkörper im obigen Beispiel mit synchronisiertem (this) ändern. Der geänderte Quellcode lautet wie folgt:
Klasse count {// Methoden, die synchronisierte Synchronisation blockieren, blockiert public void synmeThod () {synchronisiert (this) {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // Sleep for 100ms System.out.println (Thread.currentThread (). GetName () + "Synmethod Loop" + i); }} catch (InterruptedException IE) {}}} // Methoden, die synchronisierte Synchronisationsblöcke enthält, blockiert öffentliche void nonSynMethod () {synchronisiert (this) {try {for (in int i = 0; i <5; i ++) {thread.sleep (100); System.out.println (Thread.currentThread (). GetName () + "NonSynMethod Loop" + i); }} catch (InterruptedException IE) {}}}} public class Demo3 {public static void main (String [] args) {endgültig count = new count (); // T1 erstellen, T1 ruft die SynMethod () -Methode des "count -Objekt" -Threads t1 = neuer Thread (new Runnable () {@Override public void run () {count.yncMethod ();}}, "t1") auf; // Neue T2 erstellen, T2 ruft die nichtsynMethod () -Methode des "count -Objekt" -Threads t2 = neuer Thread (new Runnable () {@Override public void run () {count.nonSynMethod ();}}, "t2") auf; t1.start (); // starten t1 t2.start (); // T2}} starten Auslaufergebnisse:
T1 Synmethod Loop 0t1
Ergebnisse Beschreibung:
Zwei neue Kinderfäden T1 und T2 werden im Hauptfaden erstellt. Sowohl T1 als auch T2 rufen synchronisiert (dieses), das ein Count -Objekt (Graf) sowie T1- und T2 -Aktienzahl ist. Wenn T1 ausgeführt wird, wird T2 daher blockiert und T1 wird ausgeführt, um das "Synchronenschloss des Grafenobjekts" freizusetzen, bevor T2 ausgeführt werden kann.
3. Synchronisierte Methode und synchronisierter Codeblock
Die "synchronisierte Methode" verwendet die synchronisierte Modifikationsmethode, während der "synchronisierte Codeblock" den synchronisierten Modifikationscodeblock verwendet.
Beispiel für synchronisierte Methoden
public synchronisierte void foo1 () {System.out.println ("Synchronisierte Methode");} synchronisierter Codeblock public void foo2 () {synchronisiert (this) {System.out.println ("Synchronisierte Methode"); }} Dies im synchronisierten Codeblock bezieht sich auf das aktuelle Objekt. Dies kann auch durch andere Objekte ersetzt werden, die beispielsweise durch OBJ ersetzt werden, und foo2 () erwirbt die Synchronisationsschloss von OBJ, wenn sie synchronisiert ist (OBJ).
Synchronisierte Codeblöcke können konfliktbeschränkte Zugangsbereiche genauer steuern und manchmal effizienter abschneiden. Hier ist ein Beispiel zu demonstrieren:
// Demo4.javas Quellcode öffentliche Klasse Demo4 {public synchronisierte void synmeThod () {für (int i = 0; i <1000000; i ++); } public void synblock () {synchronized (this) {für (int i = 0; i <1000000; i ++); }} public static void main (String [] args) {Demo4 Demo = new Demo4 (); langer Start, diff; start = system.currentTimemillis (); // die aktuelle Zeit (Millis) doc.syncMethod () erhalten; // Aufrufen "Synchronisierte Methode" diff = system.currentTimillis () - start; // "Zeitdifferenz" system.out.println ("syncMethod ():"+ diff); start = system.currentTimemillis (); // die aktuelle Zeit (Millis) doc.syncBlock () erhalten; // Aufrufen "Synchronisierter Methodenblock" diff = system.currentTimillis () - Start; // "Zeitdifferenz" system.out.println ("syncBlock ():"+ diff); }} (Einmal) Ausführungsergebnis:
Synmethod (): 11synblock (): 3
4. Instanzschloss und Global Lock
Instanzschloss-auf einem Instanzobjekt gesperrt. Wenn die Klasse ein Singleton ist, hat das Schloss auch das Konzept eines globalen Schlosses.
(1) Das synchronisierte Schlüsselwort entspricht der Instanzschloss.
(2) Global Lock-Das Schloss ist auf eine Klasse abzielt. Unabhängig davon, wie viele Objekte die Instanz sind, teilen die Threads das Schloss.
Das globale Schloss entspricht statischer synchronisiertem (oder auf dem Objekt der Klasse oder des Klassenloaders dieser Klasse).
Es gibt ein sehr lebendiges Beispiel für "Instanzschloss" und "Global Lock":
Pulbic Class Etwas {public synchronisierte void isynca () {} public synchronisierte void isyncb () {} public static synchronisierte void csynca () {} öffentliche statische statische synchronisierte void void csyncb () {}}} Angenommen, etwas hat zwei Fälle x und y. Analysieren Sie die von den folgenden vier Ausdruckssätzen erworbenen Schlösser.
(1) X.ISSYNCA () und X.ISSYNCB ()
(2) X.ISSYNCA () und Y.ISSYNCA ()
(3) x.csynca () und y.csyncb ()
(4) X.ISSynca () und etwas.csynca ()
(1) kann nicht gleichzeitig zugegriffen werden.
Weil Issynca () und isSyncb () beide Synchronisationssperrungen sind, die auf dasselbe Objekt zugreifen (Objekt X)!
// lockTest1.javas Quellcode -Klasse Etwas {public synchronisierte void isynca () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // Sleep 100MS System.out.println (Thread.CurrentThread (). GetName ()+": isynca"); }} catch (InterruptedException IE) {}} public synchronisierte void isyncb () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep for 100ms System.out.println (Thread.CurrentThread (). GetName ()+": isSyncb"); }} catch (InterruptedException IE) {}}} öffentliche Klasse lockTest1 {etwas x = neu etwas (); Etwas y = neu etwas (); // vergleiche (01) X.ISSynca () mit X.ISSyncb () private void test1 () {// Neue t11 erstellen, t11 ruft X.ISSynca () Thread t11 = neuer Thread auf (neuer Runnable () {@Override public void run () {isSynca ();} {@Override); // Neue T12 erstellen, t12 ruft X.ISSyncb () Thread t12 = neuer Thread (new Runnable () {@Override public void run () {X.ISSyncb ();}}, "T12"); t11.Start (); // starten t11 t12.start (); // starten t12} public static void main (String [] args) {lockTest1 Demo = new LockTest1 (); Demo.Test1 (); }} Auslaufergebnisse:
T11: isyncat11: isyncat11: isSyncat11: isSyncat12: isSyncBt12: isSyncBt12: issyncBt12: isSyncBt12: issyncBt12: isSyncBt12: issyncbt12: isSyncBT12: isyncbbbbb
(2) kann gleichzeitig zugegriffen werden
Da es nicht auf die Synchronisationsschloss desselben Objekts zugreift, greift X.ISSynca () auf die Synchronisationsschloss von X zu, während y.issynca () auf die Synchronisationsschloss von Y zugreift.
// locktest2.javas Quellcode -Klasse Etwas {public synchronisierte void isynca () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // Sleep 100MS System.out.println (Thread.CurrentThread (). GetName ()+": isynca"); }} catch (InterruptedException IE) {}} public synchronisierte void isyncb () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName ()+": isyncb"); }} catch (InterruptedException IE) {}} public static synchronisierte void csynca () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName ()+": CSynca"); }} catch (InterruptedException IE) {}} public static synchronisierte void csyncb () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName ()+": CSYNCB"); }} catch (InterruptedException ie) {}}} public class lockTest2 {etwas x = neu etwas (); Etwas y = neu etwas (); // vergleiche (02) X.ISSynca () mit Y.ISSynca () privat void test2 () {// Neue t21 erstellen, t21 ruft X.ISSynca () Thread T21 = neuer Thread (new Runnable () {@Override Public void Run () {isSynca () ();}}}, "T21"). // Neue T22 erstellen, t22 ruft X.ISSyncb () Thread t22 = neuer Thread (new Runnable () {@Override public void run () {y.ISSynca ();}}, "T22"); t21.Start (); // T21 T22.Start () starten; // starten t22} public static void main (String [] args) {lockTest2 Demo = new LockTest2 (); Demo.Test2 (); }} Auslaufergebnisse:
t21 : isSyncAt22 : isSyncAt21 : isSyncAt22 : isSyncAt21 : isSyncAt22 : isSyncAt21 : isSyncAt22 : isSyncAt21 : isSyncAt22 : isSyncAt21 : isSyncAt22 : isSyncAt21 : isSyncAt22 : isSyncA
(3) kann nicht gleichzeitig zugegriffen werden
Da CSYNCA () und CSYNCB () beide statische Typen sind, entspricht X.csynca () etwas. ISSynca () und Y.Csyncb () entspricht etwas. ISSyncb () haben eine Synchronisationsschloss und können nicht zur gleichen Zeit gefragt werden.
// lockTest3.javas Quellcode -Klasse Etwas {public synchronisierte void isynca () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // Sleep 100MS System.out.println (Thread.CurrentThread (). GetName ()+": isynca"); }} catch (InterruptedException IE) {}} public synchronisierte void isyncb () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName ()+": isyncb"); }} catch (InterruptedException IE) {}} public static synchronisierte void csynca () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName ()+": CSynca"); }} catch (InterruptedException IE) {}} public static synchronisierte void csyncb () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName ()+": CSYNCB"); }} catch (InterruptedException IE) {}}} public class lockTest3 {etwas x = neu etwas (); Etwas y = neu etwas (); // vergleiche (03) x.csynca () mit y.csyncb () private void test3 () {// Neue t31 erstellen, t31 nennt X.ISSynca () Thread t31 = neuer Thread (neuer Runnable () {@Override Public void Run () {x.cSynca ();}}, "T31"); // Neue T32 erstellen, t32 ruft X.ISSyncb () Thread t32 = neuer Thread (new Runnable () {@Override public void run () {y.csyncb ();}}, "t32"); t31.Start (); // T31 T32.Start () starten; // starten t32} public static void main (String [] args) {lockTest3 Demo = new LockTest3 (); Demo.Test3 (); }} Auslaufergebnisse:
t31: cSyncAt31: cSyncAt31: cSyncAt31: cSyncAt31: cSyncAt32: cSyncBt32: cSyncBt32: cSyncBt32: cSyncBt32: cSyncBt32: cSyncBt32: cSyncBt32: cSyncBt32: cSyncBt32: CSYNCB
(4) kann gleichzeitig zugegriffen werden
Da isynca () eine Instanzmethode ist, verwendet X.ISSYNCA () die Sperre von Objekt x; Während CSynca () eine statische Methode ist, kann CSYNCA () verstehen, dass es sich um ein "Klassenschloss" handelt. Daher können sie gleichzeitig zugegriffen werden.
// locktest4.javas Quellcode -Klasse etwas {public synchronisierte void isynca () {try {for (int i = 0; i <5; i ++) {Thread.sleep (100); // Sleep 100MS System.out.println (Thread.CurrentThread (). GetName ()+": isynca"); }} catch (InterruptedException IE) {}} public synchronisierte void isyncb () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName ()+": isyncb"); }} catch (InterruptedException IE) {}} public static synchronisierte void csynca () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep 100MS System.out.println (Thread.currentThread (). GetName ()+": CSynca"); }} catch (InterruptedException IE) {}} public static synchronisierte void csyncb () {try {for (int i = 0; i <5; i ++) {thread.sleep (100); // Sleep for 100ms System.out.println (Thread.currentThread (). GetName ()+": csyncb"); }} catch (InterruptedException IE) {}}} public class lockTest4 {etwas x = neu etwas (); Etwas y = neu etwas (); // vergleiche (04) x.ISSynca () mit etwas.csynca () private void test4 () {// Neue t41 erstellen, t41 ruft X.ISSynca () Thread t41 = neuer Thread (new Runnable () {@Override Public void Run () {isSynca ();}}, "t41"; // Neue T42 erstellen, t42 ruft X.ISSyncb () Thread t42 = neuer Thread (new Runnable () {@Override public void run () {etwas.csynca ();}}, "T42"); t41.Start (); // T41 T42.Start () starten; // starten t42} public static void main (String [] args) {lockTest4 Demo = new LockTest4 (); Demo.Test4 (); }} Auslaufergebnisse:
T41: Issyncat42: CSYNCAT41: ISSYNCAT42: CSYNCAT41: ISSYNCAT42: CSYNCAT41: ISSYNCAT42: CSYNCAT41: ISSYNCAT42: CSYNCAT41: ISSYNCAT42: CSYNCAT41: ISSYNCAT42: CSYNCAT42: CSYNCAT41: ISSYNCAT42: CSYNCAT42: CSYNCAT41: ISSYNCAT42: CSYNCAT42: ISSYNCAT42: CSYNCAT42: ISSYNCAT42: CSYNCAT42: ISSYNCAT42: CSYNCAT42: CSYNCAT41: ISSYNCAT42: