Wenn ein Java -Sprachschlüsselwort verwendet wird, um eine Methode oder einen Codeblock zu ändern, kann sichergestellt werden, dass der Code höchstens ein Thread gleichzeitig ausführt.
1. Wenn zwei gleichzeitige Threads auf diesen synchronisierten (this) synchronisierten Codeblock in demselben Objektobjekt zugreifen, kann nur ein Thread innerhalb eines Zeitpunkts ausgeführt werden. Ein weiterer Thread muss warten, bis der aktuelle Thread diesen Codeblock ausführt, bevor er den Codeblock ausführen kann.
2. Wenn jedoch ein Thread auf einen synchronisierten (this) -Synchronisationscode-Codeblock eines Objekts zugreift, kann ein anderer Thread weiterhin auf den nicht synchronisierten (this) Synchronisationscodeblock in diesem Objekt zugreifen.
3.. Es ist besonders wichtig, dass bei einem Thread auf einen synchronisierten (this) -Synchronisationscode -Block eines Objekts zugreift, andere Threads den Zugriff auf alle anderen synchronisierten (this) -Synchronisationscodeblöcke im Objekt im Objekt blockieren.
4. Das dritte Beispiel gilt auch für andere Synchroncodeblöcke. Das heißt, wenn ein Thread auf einen synchronisierten (this) -Synchronisationscode -Codeblock eines Objekts zugreift, wird die Objektsperrung dieses Objekts erhalten. Infolgedessen werden andere Threads auf alle synchronen Code -Teile des Objektobjekts zugreifen.
5. Die oben genannten Regeln gelten auch für andere Objektschlösser.
Geben Sie ein Beispiel:
1. Wenn zwei gleichzeitige Threads auf diesen synchronisierten (this) synchronisierten Codeblock in demselben Objektobjekt zugreifen, kann nur ein Thread innerhalb eines Zeitpunkts ausgeführt werden. Ein weiterer Thread muss warten, bis der aktuelle Thread diesen Codeblock ausführt, bevor er den Codeblock ausführen kann.
Paket ths; public class Thread1 implementiert runnable {public void run () {synchronized (this) {for (int i = 0; i <5; i ++) {System.out.println (Thread.CurrentThread (). getName () + "Synchronisierte Loop" + i); }}} public static void main (String [] args) {Thread1 t1 = neuer Thread1 (); Thread Ta = neuer Thread (T1, "a"); Thread TB = neuer Thread (T1, "B"); ta.start (); tb.start (); }}Ergebnis:
Eine synchronisierte Schleife 0
Eine synchronisierte Schleife 1
Eine synchronisierte Schleife 2
Eine synchronisierte Schleife 3
Eine synchronisierte Schleife 4
B Synchronisierte Schleife 0
B Synchronisierte Schleife 1
B Synchronisierte Schleife 2
B Synchronisierte Schleife 3
B Synchronisierte Schleife 4
2. Wenn jedoch ein Thread auf einen synchronisierten (this) -Synchronisationscode-Codeblock eines Objekts zugreift, kann ein anderer Thread weiterhin auf den nicht synchronisierten (this) Synchronisationscodeblock in diesem Objekt zugreifen.
Paket ths; public class thread2 {public void m4t1 () {synchronisiert (this) {int i = 5; while (i--> 0) {System.out.println (Thread.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (InterruptedException IE) {}}}} public void m4t2 () {int i = 5; while (i--> 0) {System.out.println (Thread.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (InterruptedException dh) {}}} public static void main (String [] args) {Final Thread2 myt2 = neuer Thread2 (); Thread t1 = neuer Thread (neuer runnable () {public void run () {myt2.m4t1 ();}}, "t1"); Thread t2 = neuer Thread (neuer runnable () {public void run () {myt2.m4t2 ();}}, "t2"); t1.start (); t2.Start (); }} Ergebnis:
T1: 4
T2: 4
T1: 3
T2: 3
T1: 2
T2: 2
T1: 1
T2: 1
T1: 0
T2: 0
3.. Es ist besonders wichtig, dass bei einem Thread auf einen synchronisierten (this) -Synchronisationscode -Block eines Objekts zugreift, andere Threads den Zugriff auf alle anderen synchronisierten (this) -Synchronisationscodeblöcke im Objekt im Objekt blockieren.
// modifizieren Sie thread2.m4t2 () Methode: public void m4t2 () {synchronized (this) {int i = 5; while (i--> 0) {System.out.println (Thread.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (InterruptedException IE) {}}}}Ergebnis:
T1: 4
T1: 3
T1: 2
T1: 1
T1: 0
T2: 4
T2: 3
T2: 2
T2: 1
T2: 0
4. Das dritte Beispiel gilt auch für andere Synchroncodeblöcke. Das heißt, wenn ein Thread auf einen synchronisierten (this) -Synchronisationscode -Codeblock eines Objekts zugreift, wird die Objektsperrung dieses Objekts erhalten. Infolgedessen werden andere Threads auf alle synchronen Code -Teile des Objektobjekts zugreifen.
// Die Methode von Thread2.m4t2 () wie folgt ändern: öffentliches synchronisiertes void m4t2 () {int i = 5; while (i--> 0) {System.out.println (Thread.currentThread (). getName () + ":" + i); try {thread.sleep (500); } catch (InterruptedException dh) {}}} Ergebnis:
T1: 4
T1: 3
T1: 2
T1: 1
T1: 0
T2: 4
T2: 3
T2: 2
T2: 1
T2: 0
5. Die oben genannten Regeln gelten auch für andere Objektschlösser:
Paket ths; public class Thread3 {Klasse Inner {private void m4t1 () {int i = 5; while (i--> 0) {System.out.println (Thread.currentThread (). getName () + ": inner.m4t1 () =" + i); try {thread.sleep (500); } catch (InterruptedException IE) {}}} private void m4t2 () {int i = 5; while (i--> 0) {System.out.println (Thread.currentThread (). getName () + ": inner.m4t2 () =" + i); try {thread.sleep (500); } catch (InterruptedException IE) {}}}} private void m4t1 (innere innere) {synchronisiert (innere) {// Verwenden Sie die Objektsperrung inner.m4t1 (); } private void m4t2 (innere innere) {inner.m4t2 (); } public static void main (String [] args) {final Thread3 myt3 = neuer Thread3 (); endgültige innere innere = myt3.New Inner (); Thread t1 = neuer Thread (neuer Runnable () {public void run () {myt3.m4t1 (inner);}}, "t1"); Thread t2 = neuer Thread (neuer Runnable () {public void run () {myt3.m4t2 (inner);}}, "t2"); t1.start (); t2.Start (); }}Ergebnis:
Obwohl Thread T1 eine Objektschloss im Inneren erhält, da Thread T2 auf den asynchronen Teil im gleichen inneren Zugriff zugreift. Daher stören sich die beiden Threads nicht gegenseitig.
t1: inner.m4t1 () = 4
t2: inner.m4t2 () = 4
t1: inner.m4t1 () = 3
T2: Inner.m4t2 () = 3
T1: Inner.m4t1 () = 2
t2: inner.m4t2 () = 2
t1: inner.m4t1 () = 1
T2: Inner.m4t2 () = 1
t1: inner.m4t1 () = 0
t2: inner.m4t2 () = 0
Jetzt synchronisiert vor Inner.m4t2 ():
private synchronisierte void m4t2 () {int i = 5; while (i--> 0) {System.out.println (Thread.currentThread (). getName () + ": inner.m4t2 () =" + i); try {thread.sleep (500); } catch (InterruptedException dh) {}}}Ergebnis:
Obwohl Threads T1 und T2 auf zwei nicht verwandte Teile desselben inneren Objekts zugreifen, da T1 zuerst die Objektschloss zum Inneren erhält, ist der Zugriff von T2 auf innere.m4t2 () ebenfalls blockiert, da M4T2 () eine Synchronisationsmethode im inneren.
t1: inner.m4t1 () = 4
t1: inner.m4t1 () = 3
T1: Inner.m4t1 () = 2
t1: inner.m4t1 () = 1
t1: inner.m4t1 () = 0
t2: inner.m4t2 () = 4
T2: Inner.m4t2 () = 3
t2: inner.m4t2 () = 2
T2: Inner.m4t2 () = 1
t2: inner.m4t2 () = 0
Artikel 2:
Synchronisiertes Schlüsselwort, das zwei Verwendungen enthält: die synchronisierte Methode und den synchronisierten Block.
1. Synchronisierte Methode: Deklarieren Sie die synchronisierte Methode durch Hinzufügen des synchronisierten Schlüsselworts zur Methodenerklärung. wie:
öffentliches synchronisiertes void accessval (int newval);
Die synchronisierte Methode steuert den Zugriff auf Klassenelementvariablen: Jede Klasseninstanz entspricht einer Sperre, und jede synchronisierte Methode muss die Sperre der Klasseninstanz erhalten, die die Methode aufruft, bevor sie ausgeführt werden kann. Ansonsten ist der Faden, zu dem er gehört, blockiert. Sobald die Methode ausgeführt wurde, wird sie ausschließlich das Schloss besetzen. Das Schloss wird erst freigegeben, wenn es aus der Methode zurückkehrt. Der blockierte Thread kann das Schloss erhalten und in den ausführbaren Status eintreten. Dieser Mechanismus stellt sicher, dass gleichzeitig für jede Klasseninstanz höchstens eine der synchronisierten Mitgliedsfunktionen in einem ausführbaren Zustand (da höchstens man die Sperre erhalten kann, die der Klasseninstanz entspricht), wodurch die Zugriffskonflikte der Klassenmitgliedsvariablen effektiv vermieden werden (so lange wie alle möglichen Methoden, um Klassenmitgliedern zuzugreifen, die synchronisiert wurden).
In Java nicht nur Klasseninstanzen, sondern jede Klasse entspricht auch einer Schloss, sodass wir die statische Mitgliedsfunktion der Klasse als synchronisiert erklären können, um den Zugriff auf die statischen Mitgliedsvariablen der Klasse zu steuern.
Der Nachteil der synchronisierten Methode: Ein großes Verfahren als synchronisierte Methode wirkt sich stark auf die Effizienz aus. Wenn die Methode der Thread -Klasse run () als synchronisiert erklärt wird, wird es in einer synchronisierten Methode dieser Klasse niemals erfolgreich sein, da sie während des gesamten Lebens des Threads gelaufen ist. Natürlich können wir dieses Problem lösen, indem wir den Code, der auf die Klassenmitglied -Variablen zugreift, in eine spezielle Methode aufgenommen, ihn als synchronisiert erklärt und in der Hauptmethode aufgerufen wird. Java bietet uns jedoch eine bessere Lösung, dh den synchronisierten Block.
2. Synchronisierter Block: Deklarieren Sie den synchronisierten Block durch das synchronisierte Schlüsselwort. Die Syntax ist wie folgt:
Synchronized (SyncObject) {// Code, der Zugriffskontrolle} ermöglicht} Der synchronisierte Block ist ein Codeblock, in dem der Code eine Sperre des Objektsynkobjekts erhalten muss (wie bereits erwähnt, kann er eine Klasseninstanz oder Klasse sein), bevor er ausgeführt werden kann. Der spezifische Mechanismus ist derselbe wie oben beschrieben. Da es auf jeden Codeblock abzielen und gesperrte Objekte jederzeit angegeben werden können, ist es flexibler.
Einige Verständnisse von synchronisiertem (this) <br /> 1. Wenn zwei gleichzeitige Threads auf diesen synchronisierten (this) synchronisierten Codeblock im selben Objekt zugreifen, kann nur ein Thread innerhalb einer Zeit ausgeführt werden. Ein weiterer Thread muss warten, bis der aktuelle Thread diesen Codeblock ausführt, bevor er den Codeblock ausführen kann.
2. Wenn jedoch ein Thread auf einen synchronisierten (this) -Synchronisationscode-Codeblock eines Objekts zugreift, kann ein anderer Thread weiterhin auf den nicht synchronisierten (this) Synchronisationscodeblock in diesem Objekt zugreifen.
3.. Es ist besonders wichtig, dass bei einem Thread auf einen synchronisierten (this) -Synchronisationscode -Block eines Objekts zugreift, andere Threads den Zugriff auf alle anderen synchronisierten (this) -Synchronisationscodeblöcke im Objekt im Objekt blockieren.
4. Das dritte Beispiel gilt auch für andere Synchroncodeblöcke. Das heißt, wenn ein Thread auf einen synchronisierten (this) -Synchronisationscode -Codeblock eines Objekts zugreift, wird die Objektsperrung dieses Objekts erhalten. Infolgedessen werden andere Threads auf alle synchronen Code -Teile des Objektobjekts zugreifen.
5. Die oben genannten Regeln gelten auch für andere Objektschlösser.
So verwenden Sie in Java synchronisiert
Zum Beispiel: Ein Objekt ist wie ein großes Haus, die Tür ist immer offen. Es gibt viele Räume im Haus (dh die Methode).
Diese Räume haben gesperrt (synchronisierte Methode) und sind nicht gesperrt (normale Methode). Es gibt einen Schlüssel an der Tür, der alle verschlossenen Räume öffnen kann.
Außerdem vergleiche ich alle Themen, die die Objektmethode mit Personen bezeichnen möchten, die einen Raum in diesem Haus betreten möchten. Es gibt nur so viele Dinge, sehen wir sehen, wie diese Dinge funktionieren.
Hier klären wir zuerst unsere Voraussetzungen. Das Objekt hat mindestens eine synchronisierte Methode, ansonsten, was ist der Sinn dieses Schlüssels? Natürlich wird es für uns kein solches Thema geben.
Ein Mann wollte einen verschlossenen Raum betreten. Er kam zur Tür des Hauses und sah dort den Schlüssel (es bedeutet, dass noch niemand den verschlossenen Raum benutzen möchte). Also ging er auf und holte die Schlüssel und benutzte die Räume, wie er es plante. Seien Sie sich bewusst, dass er den Schlüssel sofort nach der Verwendung des verschlossenen Raums jedes Mal zurückgeben wird. Selbst wenn er zwei verschlossene Räume hintereinander verwenden möchte, wird er die Schlüssel zurückgeben, um sie abzurufen. Daher lautet das Prinzip der Verwendung eines Schlüssels in gewöhnlichen Fällen: "Leihen Sie ihn bei und senden Sie ihn zurück, sobald Sie ihn verwenden."
Zu diesem Zeitpunkt können andere Personen diese entsperrten Räume ohne Einschränkungen nutzen. Eine Person kann einen Raum benutzen, und zwei Personen können einen Raum ohne Einschränkungen benutzen. Aber wenn jemand einen verschlossenen Raum betreten möchte, muss er zum Tor rennen, um einen Blick darauf zu werfen. Wenn Sie den Schlüssel haben, werden Sie natürlich gehen. Wenn Sie es nicht haben, können Sie nur warten. Wenn viele Leute auf diesen Schlüssel warten, wer bekommt dann zuerst den Schlüssel, nachdem er zurückgekehrt ist? Nicht garantiert. Wie der Typ im vorherigen Beispiel, der zwei verschlossene Räume hintereinander verwenden wollte, gab es keine Garantie dafür, dass dieser Typ es wieder bekommen würde, wenn andere Leute auf die Schlüssel in der Mitte warteten. (Die Java -Spezifikation besagt deutlich, dass sie an vielen Stellen nicht garantiert ist, wie lange es für den Thread dauert. Zustand, aber basierend auf vielen Artikeln.
Da es zu viele Urteilsbedingungen gibt, kann dies, wenn Sie es sagen, die Förderung von Java beeinflussen, oder es kann auf Schutz des geistigen Eigentums zurückzuführen sein. Sun gab mir ein Versprechen und kam durch. Es ist nichts falsch daran. Aber ich glaube, diese Unsicherheiten sind nicht ganz ungewiss. Weil der Computer selbst nach Anweisungen ausgeführt wird. Auch wenn das Phänomen zufällig erscheint, ist es tatsächlich regelmäßig. Jeder, der Computer untersucht hat, weiß, dass der wissenschaftliche Name von Zufallszahlen in Computern Pseudo-Random-Zahlen sind, die von Personen geschrieben werden, die bestimmte Methoden anwenden, und sie sehen nur zufällig aus. Außerdem liegt es vielleicht daran, dass es zu schwierig ist, sicher und nicht sehr aussagekräftig zu sein. Wenn Sie also nicht sicher sind, sind Sie sich nicht sicher. )
Schauen wir uns den Synchronisierungscodeblock an. Es gibt einen kleinen Unterschied zu der Synchronisationsmethode.
1. In Bezug auf die Größe ist der Synchronisationscodeblock kleiner als die Synchronisationsmethode. Sie können sich den Synchronisierungscodeblock als Platz in einem entsperrten Raum vorstellen, der durch einen verschlossenen Bildschirm getrennt ist.
2. Der Synchronisationscode -Block kann auch künstlich den Schlüssel zum Erhalten eines bestimmten anderen Objekts angeben. Genau wie angeben, welcher Schlüssel zum Entsperren des Bildschirms, können Sie den Schlüssel dieses Raums verwenden. Sie können auch angeben, dass der Schlüssel eines anderen Hauses es öffnen kann. Auf diese Weise müssen Sie zu einem anderen Haus rennen, um diesen Schlüssel zu bringen und den Schlüssel dieses Hauses zu verwenden, um den verschlossenen Bildschirm dieses Hauses zu öffnen.
Denken Sie daran, dass der Schlüssel zu diesem anderen Haus, das Sie erhalten haben, nicht andere Personen betrifft, die ohne Schlösser in diesem Haus den Raum betreten.
Warum synchrone Codeblöcke verwenden? Ich denke, es sollte so sein: Zunächst hat der Synchronisationsteil des Programms einen großen Einfluss auf die Betriebseffizienz, und eine Methode besteht normalerweise darin, zuerst einige lokale Variablen zu erstellen und dann einige Operationen auf diesen Variablen wie Vorgängen, Anzeigen usw.; Und je mehr Code von Synchronisation abgedeckt ist, desto schwerwiegender die Auswirkungen auf die Effizienz. Daher versuchen wir normalerweise, seine Wirkung einzugrenzen.
Wie macht ich das? Codeblockungen synchronisieren. Wir synchronisieren nur die Synchronisationsplätze in einer Methode, wie z. B. Operationen.
Darüber hinaus hat die Funktion von synchronen Codeblöcken, die Schlüssel angeben können, einen zusätzlichen Vorteil, nämlich die Tasten eines Objekts innerhalb eines bestimmten Zeitraums. Erinnern Sie sich an die Prinzipien der Verwendung von Schlüsseln in gewöhnlichen Situationen, die zuvor erwähnt wurden? Es ist jetzt nicht die gewöhnliche Situation. Der Schlüssel, den Sie erhalten haben, wird nie zurückgegeben, sondern nur dann zurückgegeben, wenn Sie den Synchroncode -Block beenden.
Ich benutzte auch den Kerl vor dem, der zwei verschlossene Räume hintereinander verwenden wollte, um ein Beispiel zu machen. Wie kann ich nach der Verwendung weiterhin einen anderen verwenden? Verwenden Sie Synchroncodeblöcke. Erstellen Sie zuerst einen weiteren Thread, erstellen Sie einen synchronen Codeblock und weisen Sie die Sperre dieses Codeblocks auf den Schlüssel des Hauses an. Dann starten Sie diesen Thread. Solange Sie den Schlüssel zum Haus beim Eingeben in diesen Codeblock aufnehmen können, können Sie ihn aufbewahren, bis Sie diesen Codeblock beenden. Mit anderen Worten, Sie können sogar alle verschlossenen Räume in diesem Raum oder sogar Schlaf (10*60*1000) durchqueren, und es warten noch 1.000 Fäden, die auf diesen Schlüssel an der Tür warten. Sehr erfreulich.
Hier sprechen wir über die Korrelation zwischen der Sleep () -Methode und dem Schlüssel. Wenn ein Thread nach dem Erhalten des Schlüssels gezwungen ist () und den synchronen Inhalt nicht abgeschlossen hat, ist der Schlüssel noch da. Der Schlüssel wird erst zurückgegeben, wenn er erneut ausgeführt wird und alle synchronen Inhalte abgeschlossen wird. Denken Sie daran, dieser Typ hatte es nur müde zu arbeiten, also machte er eine Pause und er beendete nicht, was er tun würde. Um zu vermeiden, dass andere den Raum betreten und ein Chaos machen, muss er den einzigen Schlüssel für seinen Körper tragen, selbst wenn er schläft.
Schließlich fragen einige Leute vielleicht, warum Sie einen Schlüssel zum Öffnen anstelle eines Schlüssels und einer Tür benötigen. Ich denke, das liegt nur an die Komplexität. Natürlich sind ein Schlüssel und eine Tür sicherer, aber es wird viele Probleme beinhalten. Generation, Speicherung, Akquisition, Rückgabe usw. von Schlüssel. Seine Komplexität kann die geometrischen Sequenzen mit zunehmender Synchronisationsmethode erhöhen, was die Effizienz ernsthaft beeinflusst. Dies ist auch ein Kompromiss. Wie unerwünscht ist, die Sicherheit ein wenig zu erhöhen, was zu einer signifikanten Verringerung der Effizienz führt.
Ein einfaches Beispiel für synchronisiert
public class textThread {public static void main (String [] args) {txtThread tt = new txtThread (); neuer Thread (tt) .Start (); neuer Thread (tt) .Start (); neuer Thread (tt) .Start (); neuer Thread (tt) .Start (); }} class txtThread implementiert runnable {int num = 100; String str = new String (); public void run () {synchronized (str) {while (num> 0) {try {thread.sleep (1); } catch (Ausnahme e) {e.getMessage (); } System.out.println (Thread.currentThread (). GetName () + "this is" + num--); }}}}Im obigen Beispiel, um einen Zeitunterschied zu erzeugen, dh die Möglichkeit, einen Fehler zu machen, wird Thread.Sleep (10) verwendet.
Der Unterstützung und Synchronisationsmechanismus von Java für Multithreading ist sehr beliebt. Die Verwendung des synchronisierten Schlüsselworts kann das Problem der Multithread -Shared -Datensynchronisation leicht lösen. Was genau? Es ist auch notwendig, ein umfassendes Verständnis der Rolle synchronisierter Schlüsselwörter zu haben, bevor Sie eine Schlussfolgerung ziehen können.
Im Allgemeinen kann das synchronisierte Schlüsselwort als Modifikator der Funktion oder als Anweisung innerhalb der Funktion verwendet werden. Dies ist die normalerweise erwähnte Synchronisationsmethode und Synchronisationsanweisung. Wenn Sie es sorgfältiger klassifizieren, kann synchronisiert auf Instanzvariablen, Objektreferenzen, statische Funktionen und Klassenliterale (Klassenname Literalkonstanten) wirken.
Bevor wir weiter ausgehen, müssen wir einige Punkte klären:
A. Unabhängig davon
Objektzugriff auf seinen Thread.
B. Jedes Objekt hat nur ein Schloss zugeordnet.
C. Die Implementierung der Synchronisation erfordert viel Systemaufwand als Kosten und kann sogar zu Deadlocks führen. Versuchen Sie daher, eine unnötige Synchronisationskontrolle zu vermeiden.
Lassen Sie uns als nächstes die Auswirkungen von synchronisiertem Synchron mit verschiedenen Orten auf dem Code erörtern:
Unter der Annahme, dass P1 und P2 unterschiedliche Objekte derselben Klasse sind, definiert diese Klasse Synchronisationsblöcke oder Synchronisationsmethoden in den folgenden Situationen, und P1 und P2 können sie aufrufen.
1. Wenn synchronisiert wird, wird der Beispielcode wie folgt verwendet:
Public synchronisierte void methodaaaa () {//….}Dies ist die Synchronisationsmethode. Welches Objekt ist zu diesem Zeitpunkt synchronisiert? Was es sperrt, ist, dieses Synchron -Method -Objekt zu nennen. Das heißt, wenn ein Objekt P1 diese Synchronisationsmethode in verschiedenen Threads ausführt, wird zwischen ihnen ein gegenseitiger Ausschluss gebildet, um den Effekt der Synchronisation zu erreichen. Ein weiteres Objekt P2, das von der Klasse generiert wird, zu der dieses Objekt gehört, kann diese Methode mit dem hinzugefügten synchronisierten Schlüsselwort willkürlich willkürlich aufrufen.
Der obige Beispielcode entspricht dem folgenden Code:
public void methodaaaa () {synchronisiert (this) // (1) {//… ..}}(1) Was bedeutet das am Punkt? Es bezieht sich auf das Objekt, das diese Methode nennt, wie z. B. P1. Es ist ersichtlich, dass die Synchronisationsmethode im Wesentlichen dazu dient, synchronisiert auf die Objektreferenz anzuwenden. Nur der Thread, der die P1 -Objektschloss erhalten hat, kann die P1 -Synchronisationsmethode aufrufen. Für P2 hat das P1 -Schloss nichts damit zu tun. Das Programm kann auch die Kontrolle des Synchronisationsmechanismus in dieser Situation beseitigen und Datenverwirrung verursachen: (
2. Synchronisieren Sie Blöcke, der Beispielcode lautet wie folgt:
public void method3 (einigeObject so) {synchronisiert (so) {//… ..}}Zu diesem Zeitpunkt ist das Schloss das Objekt von SO. Wer das Schloss erhält, kann den Code ausführen, den es steuert. Wenn es ein klares Objekt als Schloss gibt, können Sie das Programm wie dieses schreiben, aber wenn es kein klares Objekt als Sperre gibt und nur einen Code -Stück synchronisieren möchte, können Sie eine spezielle Instanzvariable (es muss ein Objekt sein) als Sperre erstellen:
Klasse foo implementiert runnable {private byte [] lock = new byte [0]; // Spezielle Instanzvariable public void methoda () {synchronized (lock) {//…}} //… ..}HINWEIS: Byte-Array-Objekte mit Zero-Length-Array sind wirtschaftlicher als jedes Objekt, um einen kompilierten Byte-Code zu erstellen: Nur 3 Opcodes sind erforderlich, um ein BYTE [] -Objekt mit Null-Länge zu generieren, während Object Lock = New Object () 7 Opcodes erfordert.
3.. Verwenden Sie synchronisiert bis zur statischen Funktion, der Beispielcode lautet wie folgt:
Klasse foo {public synchronisierte statische void methodaaa () // Synchronisierte statische Funktion {//…. } public void methodbbb () {synchronized (foo.class) // Klasse Literal (Klassenname Literalkonstante)}}}}}}}}}}}}}}}}}}}}}}}}}}}}Die Methodebbb () -Methode im Code verwendet Klassenliteral als Sperre. Es hat den gleichen Effekt wie die synchronisierte statische Funktion. Das erhaltene Schloss ist etwas ganz Besonderes. Es ist die Klasse, zu der das Objekt, das derzeit diese Methode nennt, gehört (Klasse, nicht ein bestimmtes Objekt, das von dieser Klasse generiert wird).
Ich erinnere mich, dass ich in dem Buch "Effektiver Java" gesehen habe, dass die Verwendung von Foo.class und p1.getClass () als synchrone Sperren unterschiedlich ist und p1.getClass () nicht verwendet werden kann, um den Zweck der Verriegelung dieser Klasse zu erreichen. P1 bezieht sich auf ein von der FOO -Klasse erzeugter Objekt.
Es kann geschlossen werden, dass, wenn eine Klasse eine synchronisierte statische Funktion A und eine synchronisierte Instanzfunktion B definiert, das gleiche Objekt OBJ dieser Klasse bei dem Zugriff auf zwei Methoden A und B in mehreren Threads keine Synchronisation darstellt, da ihre Schlösser unterschiedlich sind. Die Verriegelung der Methode A ist das Objekt OBJ, während das Schloss von B die Klasse ist, zu der OBJ gehört.
Die Zusammenfassung lautet wie folgt:
Wenn Sie herausfinden, welche synchronisierten Objektschlösser sicherer mit Multi-Threaden-Programmen entwerfen können. Es gibt auch einige Tipps, um den synchronen Zugriff auf gemeinsame Ressourcen sicherer zu gestalten:
1. Definieren Sie die Instanzvariable von privat + seine GET -Methode anstelle der Instanzvariablen von öffentlich/geschützt. Wenn eine Variable als öffentlich definiert ist, kann das Objekt die Kontrolle der Synchronisationsmethode umgehen und direkt erhalten und ändern. Dies ist auch eine der Standard -Implementierungsmethoden von Javabäen.
2. Wenn es sich bei der Instanzvariablen um ein Objekt wie ein Array oder eine Arraylist handelt, ist die obige Methode immer noch unsicher, da ein externes Objekt den Verweis auf das Instanzobjekt über die GET -Methode erhält und auf ein anderes Objekt zeigt, ändert sich die private Variable, was nicht sehr gefährlich ist. Zu diesem Zeitpunkt müssen Sie zur GET -Methode synchronisiert und nur den Clone () dieses privaten Objekts zurückgeben, damit der Anrufer den Verweis auf die Objektkopie erhält
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.