Ich habe einige Fragen zur Verwendung und Bedeutung des synchronized
Schlüsselworts.
- Welche Bedeutung hat das
synchronized
Schlüsselwort? - Wann sollten Methoden sein
synchronized
? - Was bedeutet es programmatisch und logisch?
Ich habe einige Fragen zur Verwendung und Bedeutung des synchronized
Schlüsselworts.
synchronized
Schlüsselwort?synchronized
?Antworten:
Das synchronized
Schlüsselwort handelt von verschiedenen Threads, die in dieselben Variablen, Objekte und Ressourcen lesen und schreiben. Dies ist kein triviales Thema in Java, aber hier ist ein Zitat von Sun:
synchronized
Methoden ermöglichen eine einfache Strategie zur Vermeidung von Thread-Interferenzen und Speicherkonsistenzfehlern: Wenn ein Objekt für mehr als einen Thread sichtbar ist, werden alle Lese- oder Schreibvorgänge in die Variablen dieses Objekts über synchronisierte Methoden ausgeführt.
Kurz gesagt: Wenn Sie zwei Threads haben, die in derselben 'Ressource' lesen und schreiben, beispielsweise eine Variable mit dem Namen foo
, müssen Sie sicherstellen, dass diese Threads auf atomare Weise auf die Variable zugreifen. Ohne das synchronized
Schlüsselwort sieht Ihr Thread 1 möglicherweise nicht, dass der Änderungsthread 2 vorgenommen wurde foo
, oder schlimmer noch, er wird möglicherweise nur zur Hälfte geändert. Dies ist nicht das, was Sie logischerweise erwarten.
Auch dies ist in Java ein nicht triviales Thema. Weitere Informationen finden Sie hier auf SO und in den Interwebs zu folgenden Themen:
Erforschen Sie diese Themen so lange, bis der Name "Brian Goetz" dauerhaft mit dem Begriff "Parallelität" in Ihrem Gehirn in Verbindung gebracht wird.
Nun, ich denke, wir hatten genug theoretische Erklärungen, also denken Sie an diesen Code
public class SOP {
public static void print(String s) {
System.out.println(s+"\n");
}
}
public class TestThread extends Thread {
String name;
TheDemo theDemo;
public TestThread(String name,TheDemo theDemo) {
this.theDemo = theDemo;
this.name = name;
start();
}
@Override
public void run() {
theDemo.test(name);
}
}
public class TheDemo {
public synchronized void test(String name) {
for(int i=0;i<10;i++) {
SOP.print(name + " :: "+i);
try{
Thread.sleep(500);
} catch (Exception e) {
SOP.print(e.getMessage());
}
}
}
public static void main(String[] args) {
TheDemo theDemo = new TheDemo();
new TestThread("THREAD 1",theDemo);
new TestThread("THREAD 2",theDemo);
new TestThread("THREAD 3",theDemo);
}
}
Hinweis: synchronized
Blockiert den Aufruf des nächsten Threads an method test (), solange die Ausführung des vorherigen Threads nicht abgeschlossen ist. Threads können einzeln auf diese Methode zugreifen. Ohne synchronized
alle Threads kann gleichzeitig auf diese Methode zugegriffen werden.
Wenn ein Thread die synchronisierte Methode 'test' des Objekts aufruft (hier ist das Objekt eine Instanz der 'TheDemo'-Klasse), erhält er die Sperre dieses Objekts. Ein neuer Thread kann KEINE synchronisierte Methode desselben Objekts aufrufen, solange der vorherige Thread Wer das Schloss erworben hat, gibt das Schloss nicht frei.
Ähnliches passiert, wenn eine statisch synchronisierte Methode der Klasse aufgerufen wird. Der Thread erhält die der Klasse zugeordnete Sperre (in diesem Fall kann jede nicht statische synchronisierte Methode einer Instanz dieser Klasse von jedem Thread aufgerufen werden, da diese Sperre auf Objektebene noch verfügbar ist). Ein anderer Thread kann keine statisch synchronisierte Methode der Klasse aufrufen, solange die Sperre auf Klassenebene nicht von dem Thread freigegeben wird, der derzeit die Sperre enthält.
Ausgabe mit synchronisiert
THREAD 1 :: 0
THREAD 1 :: 1
THREAD 1 :: 2
THREAD 1 :: 3
THREAD 1 :: 4
THREAD 1 :: 5
THREAD 1 :: 6
THREAD 1 :: 7
THREAD 1 :: 8
THREAD 1 :: 9
THREAD 3 :: 0
THREAD 3 :: 1
THREAD 3 :: 2
THREAD 3 :: 3
THREAD 3 :: 4
THREAD 3 :: 5
THREAD 3 :: 6
THREAD 3 :: 7
THREAD 3 :: 8
THREAD 3 :: 9
THREAD 2 :: 0
THREAD 2 :: 1
THREAD 2 :: 2
THREAD 2 :: 3
THREAD 2 :: 4
THREAD 2 :: 5
THREAD 2 :: 6
THREAD 2 :: 7
THREAD 2 :: 8
THREAD 2 :: 9
Ausgabe ohne synchronisiert
THREAD 1 :: 0
THREAD 2 :: 0
THREAD 3 :: 0
THREAD 1 :: 1
THREAD 2 :: 1
THREAD 3 :: 1
THREAD 1 :: 2
THREAD 2 :: 2
THREAD 3 :: 2
THREAD 1 :: 3
THREAD 2 :: 3
THREAD 3 :: 3
THREAD 1 :: 4
THREAD 2 :: 4
THREAD 3 :: 4
THREAD 1 :: 5
THREAD 2 :: 5
THREAD 3 :: 5
THREAD 1 :: 6
THREAD 2 :: 6
THREAD 3 :: 6
THREAD 1 :: 7
THREAD 2 :: 7
THREAD 3 :: 7
THREAD 1 :: 8
THREAD 2 :: 8
THREAD 3 :: 8
THREAD 1 :: 9
THREAD 2 :: 9
THREAD 3 :: 9
synchronized
, aber die Speicherkonsistenz wird ignoriert.
Das synchronized
Schlüsselwort verhindert den gleichzeitigen Zugriff mehrerer Threads auf einen Code- oder Objektblock. Alle Methoden von Hashtable
are synchronized
sind so, dass jeweils nur ein Thread sie ausführen kann.
Wenn Sie Nicht- synchronized
Konstrukte wie verwenden HashMap
, müssen Sie Thread-Sicherheitsfunktionen in Ihrem Code erstellen, um Konsistenzfehler zu vermeiden.
synchronized
bedeutet, dass in einer Umgebung mit mehreren Threads ein Objekt mit synchronized
Methode (n) / Block (en) nicht zwei Threads gleichzeitig auf die synchronized
Methode (n) / Block (e) des Codes zugreifen lässt . Dies bedeutet, dass ein Thread nicht lesen kann, während ein anderer Thread ihn aktualisiert.
Der zweite Thread wartet stattdessen, bis der erste Thread seine Ausführung abgeschlossen hat. Der Overhead ist die Geschwindigkeit, aber der Vorteil ist die garantierte Datenkonsistenz.
Wenn Ihre Anwendung jedoch Single-Threaded ist, synchronized
bieten Blöcke keine Vorteile.
Das synchronized
Schlüsselwort bewirkt, dass ein Thread bei der Eingabe der Methode eine Sperre erhält, sodass nur ein Thread die Methode gleichzeitig ausführen kann (für die angegebene Objektinstanz, sofern es sich nicht um eine statische Methode handelt).
Dies wird häufig als Thread-sicher bezeichnet, aber ich würde sagen, dass dies ein Euphemismus ist. Zwar schützt die Synchronisierung den internen Status des Vektors vor Beschädigung, dies hilft dem Benutzer von Vector jedoch normalerweise nicht viel.
Bedenken Sie:
if (vector.isEmpty()){
vector.add(data);
}
Obwohl die beteiligten Methoden synchronisiert sind, weil sie einzeln gesperrt und entsperrt werden, können zwei leider zeitgesteuerte Threads einen Vektor mit zwei Elementen erstellen.
Tatsächlich müssen Sie also auch Ihren Anwendungscode synchronisieren.
Da die Synchronisation auf Methodenebene a) teuer ist, wenn Sie sie nicht benötigen, und b) unzureichend ist, wenn Sie eine Synchronisation benötigen, gibt es jetzt nicht synchronisierte Ersetzungen (ArrayList im Fall von Vector).
In jüngerer Zeit wurde das Parallelitätspaket mit einer Reihe cleverer Dienstprogramme veröffentlicht, die sich um Multithreading-Probleme kümmern.
Das synchronisierte Schlüsselwort in Java hat mit der Thread-Sicherheit zu tun, dh wenn mehrere Threads dieselbe Variable lesen oder schreiben.
Dies kann direkt (durch Zugriff auf dieselbe Variable) oder indirekt (durch Verwendung einer Klasse, die eine andere Klasse verwendet, die auf dieselbe Variable zugreift) geschehen.
Das synchronisierte Schlüsselwort wird verwendet, um einen Codeblock zu definieren, in dem mehrere Threads auf sichere Weise auf dieselbe Variable zugreifen können.
In Bezug auf die Syntax synchronized
nimmt das Schlüsselwort a Object
als Parameter (als Sperrobjekt bezeichnet ) an, gefolgt von a { block of code }
.
Wenn die Ausführung dieses Schlüsselwort trifft, der aktuelle Thread versucht, „lock / acquire / eigenen“ (nehmen Sie Ihre Wahl) , um das Sperrobjekt hat und führen Sie den zugehörigen Code - Block , nachdem die Sperre erworben.
Alle Schreibvorgänge in Variablen innerhalb des synchronisierten Codeblocks sind garantiert für jeden anderen Thread sichtbar, der Code in einem synchronisierten Codeblock mit demselben Sperrobjekt auf ähnliche Weise ausführt .
Es kann jeweils nur ein Thread die Sperre halten. Während dieser Zeit warten alle anderen Threads, die versuchen, dasselbe Sperrobjekt zu erhalten , (halten ihre Ausführung an). Die Sperre wird aufgehoben, wenn die Ausführung den synchronisierten Codeblock verlässt.
Hinzufügen synchronized
Schlüsselwort zu einer Methodendefinition ist gleich den gesamte Verfahren Körper in einem synchronisierten Codeblock mit eingewickelt Sperrobjekt Wesen this
(beispielsweise Methoden) und ClassInQuestion.getClass()
(für Klassenmethoden) .
- Die Instanzmethode ist eine Methode ohne static
Schlüsselwort.
- Die Klassenmethode ist eine Methode mit einem static
Schlüsselwort.
Ohne Synchronisation kann nicht garantiert werden, in welcher Reihenfolge die Lese- und Schreibvorgänge stattfinden, wodurch möglicherweise die Variable mit Müll belassen wird.
(Zum Beispiel könnte eine Variable die Hälfte der von einem Thread geschriebenen Bits und die Hälfte der von einem anderen Thread geschriebenen Bits enthalten, wodurch die Variable in einem Zustand verbleibt, den keiner der Threads zu schreiben versucht hat, sondern ein kombiniertes Durcheinander von beiden.)
Es reicht nicht aus, einen Schreibvorgang in einem Thread abzuschließen, bevor (Wanduhrzeit) ein anderer Thread ihn liest, da die Hardware den Wert der Variablen zwischengespeichert haben könnte und der Lesethread den zwischengespeicherten Wert anstelle dessen sehen würde, in den geschrieben wurde es.
In Javas Fall müssen Sie daher dem Java-Speichermodell folgen, um sicherzustellen, dass keine Threading-Fehler auftreten.
Mit anderen Worten: Verwenden Sie Synchronisation, atomare Operationen oder Klassen, die sie für Sie unter der Haube verwenden.
Quellen
http://docs.oracle.com/javase/specs/jls/se8/html/index.html
Java®-Sprachspezifikation, 13.02.2015
Stellen Sie sich das als eine Art Drehkreuz vor, wie Sie es auf einem Fußballplatz finden könnten. Es gibt parallele Dämpfe von Menschen, die einsteigen wollen, aber am Drehkreuz sind sie "synchronisiert". Es kann immer nur eine Person durchkommen. Alle, die durchkommen wollen, werden es tun, aber sie müssen möglicherweise warten, bis sie durchkommen können.
Was ist das synchronisierte Schlüsselwort?
Threads kommunizieren hauptsächlich durch gemeinsame Nutzung des Zugriffs auf Felder und die Objekte, auf die sich Referenzfelder beziehen. Diese Form der Kommunikation ist äußerst effizient, ermöglicht jedoch zwei Arten von Fehlern: Thread-Interferenz und Speicherkonsistenzfehler . Das zur Vermeidung dieser Fehler erforderliche Tool ist die Synchronisation.
Synchronisierte Blöcke oder Methoden verhindern Thread-Interferenzen und stellen sicher, dass die Daten konsistent sind. Zu jedem Zeitpunkt kann nur ein Thread auf einen synchronisierten Block oder eine synchronisierte Methode ( kritischer Abschnitt ) zugreifen, indem er eine Sperre erwirbt. Andere Threads warten auf die Freigabe der Sperre, um auf den kritischen Abschnitt zuzugreifen .
Wann werden Methoden synchronisiert?
Methoden werden synchronisiert, wenn Sie sie synchronized
zur Methodendefinition oder -deklaration hinzufügen . Sie können einen bestimmten Codeblock auch mit einer Methode synchronisieren.
Was bedeutet es programmatisch und logisch?
Dies bedeutet, dass nur ein Thread durch Erwerb einer Sperre auf einen kritischen Abschnitt zugreifen kann . Sofern dieser Thread diese Sperre nicht aufhebt, müssen alle anderen Threads warten, um eine Sperre zu erhalten. Sie haben keinen Zugriff auf den kritischen Bereich , ohne eine Sperre zu erhalten.
Dies kann nicht mit Magie geschehen. Es liegt in der Verantwortung des Programmierers, kritische Abschnitte in der Anwendung zu identifizieren und entsprechend zu schützen. Java bietet ein Framework zum Schutz Ihrer Anwendung, aber wo und was alle zu schützenden Abschnitte sind, liegt in der Verantwortung des Programmierers.
Weitere Details von Java - Dokumentation Seite
Eigensperren und Synchronisation:
Die Synchronisierung basiert auf einer internen Entität, die als intrinsische Sperre oder Monitorsperre bezeichnet wird. Intrinsische Sperren spielen in beiden Aspekten der Synchronisation eine Rolle: Erzwingen des exklusiven Zugriffs auf den Status eines Objekts und Herstellen von Vor-Vor-Beziehungen, die für die Sichtbarkeit wesentlich sind.
Jedem Objekt ist eine intrinsische Sperre zugeordnet . Gemäß der Konvention muss ein Thread, der exklusiven und konsistenten Zugriff auf die Felder eines Objekts benötigt, die intrinsische Sperre des Objekts abrufen, bevor er auf sie zugreift, und dann die intrinsische Sperre aufheben, wenn sie damit fertig ist.
Ein Thread soll die intrinsische Sperre zwischen dem Zeitpunkt, zu dem er die Sperre erworben und die Sperre freigegeben hat, besitzen. Solange ein Thread eine intrinsische Sperre besitzt, kann kein anderer Thread dieselbe Sperre erhalten. Der andere Thread wird blockiert, wenn er versucht, die Sperre zu erlangen.
Wenn ein Thread eine intrinsische Sperre aufhebt, wird eine Beziehung zwischen dieser Aktion und jeder nachfolgenden Erfassung derselben Sperre hergestellt.
Das Synchronisieren von Methoden hat zwei Auswirkungen :
Erstens ist es nicht möglich, dass zwei Aufrufe synchronisierter Methoden für dasselbe Objekt verschachtelt werden.
Wenn ein Thread eine synchronisierte Methode für ein Objekt ausführt, blockieren alle anderen Threads, die synchronisierte Methoden für denselben Objektblock aufrufen (Ausführung aussetzen), bis der erste Thread mit dem Objekt fertig ist.
Zweitens wird beim Beenden einer synchronisierten Methode automatisch eine Vorher-Beziehung zu einem nachfolgenden Aufruf einer synchronisierten Methode für dasselbe Objekt hergestellt.
Dies garantiert, dass Änderungen am Status des Objekts für alle Threads sichtbar sind.
Suchen Sie nach anderen Alternativen zur Synchronisation in:
Synchronized normal method
äquivalent zu
Synchronized statement
(benutze dies)
class A {
public synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(this) {
// all function code
}
}
}
Synchronized static method
äquivalent zu Synchronized statement
(Klasse verwenden)
class A {
public static synchronized void methodA() {
// all function code
}
equivalent to
public void methodA() {
synchronized(A.class) {
// all function code
}
}
}
Synchronisierte Anweisung (unter Verwendung einer Variablen)
class A {
private Object lock1 = new Object();
public void methodA() {
synchronized(lock1 ) {
// all function code
}
}
}
Denn synchronized
wir haben beide Synchronized Methods
und Synchronized Statements
. Ist Synchronized Methods
jedoch ähnlich, Synchronized Statements
so müssen wir nur verstehen Synchronized Statements
.
=> Grundsätzlich werden wir haben
synchronized(object or class) { // object/class use to provides the intrinsic lock
// code
}
Hier sind 2 Gedanken, die zum Verständnis beitragen synchronized
intrinsic lock
zugeordnet.synchronized statement
, erfasst er automatisch das intrinsic lock
für dieses synchronized statement's
Objekt und gibt es frei, wenn die Methode zurückkehrt. Solange ein Thread einen besitzt intrinsic lock
, kann KEIN anderer Thread die gleiche Sperre erhalten => threadsicher.=> Wenn ein thread A
Aufruf synchronized(this){// code 1}
=> ist der gesamte Blockcode (innerhalb der Klasse) wo synchronized(this)
und alle synchronized normal method
(innerhalb der Klasse) wegen der gleichen Sperre gesperrt . Es wird nach dem thread A
Entsperren ausgeführt ("// Code 1" beendet).
Dieses Verhalten ähnelt synchronized(a variable){// code 1}
oder synchronized(class)
.
SAME LOCK => lock (nicht abhängig von welcher Methode? Oder welchen Anweisungen?)
Ich bevorzuge, synchronized statements
weil es erweiterbarer ist. In Zukunft müssen Sie beispielsweise nur einen Teil der Methode synchronisieren. Beispiel: Sie haben zwei synchronisierte Methoden, die für einander nicht relevant sind. Wenn ein Thread jedoch eine Methode ausführt, blockiert er die andere Methode (dies kann durch Verwendung verhindert werden synchronized(a variable)
).
Das Anwenden der synchronisierten Methode ist jedoch einfach und der Code sieht einfach aus. Für einige Klassen gibt es nur eine synchronisierte Methode oder alle synchronisierten Methoden in der Klasse, die für einander relevant sind => Wir können synchronized method
den Code kürzer und verständlicher machen
(es ist nicht zu relevant für viel synchronized
, es ist der Unterschied zwischen Objekt und Klasse oder nicht statisch und statisch).
synchronized
oder normale Methode oder synchronized(this)
oder synchronized(non-static variable)
Base auf jeder Objektinstanz wird es synchronisiert. synchronized
statische Methode verwenden oder synchronized(class)
oder synchronized(static variable)
sie wird basierend auf der Klasse synchronisierthttps://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html
Hoffe es hilft
Hier ist eine Erklärung aus den Java-Tutorials .
Betrachten Sie den folgenden Code:
public class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; } public synchronized void decrement() { c--; } public synchronized int value() { return c; } }
Wenn dies
count
eine Instanz von istSynchronizedCounter
, hat das Synchronisieren dieser Methoden zwei Auswirkungen:
- Erstens ist es nicht möglich, dass zwei Aufrufe synchronisierter Methoden für dasselbe Objekt verschachtelt werden. Wenn ein Thread eine synchronisierte Methode für ein Objekt ausführt, blockieren alle anderen Threads, die synchronisierte Methoden für denselben Objektblock aufrufen (Ausführung aussetzen), bis der erste Thread mit dem Objekt fertig ist.
- Zweitens wird beim Beenden einer synchronisierten Methode automatisch eine Vorher-Beziehung zu einem nachfolgenden Aufruf einer synchronisierten Methode für dasselbe Objekt hergestellt. Dies garantiert, dass Änderungen am Status des Objekts für alle Threads sichtbar sind.
Nach meinem Verständnis bedeutet synchronisiert im Grunde, dass der Compiler eine monitor.enter und eine monitor.exit um Ihre Methode schreibt. Als solches kann es threadsicher sein, abhängig davon, wie es verwendet wird (ich meine, Sie können ein Objekt mit synchronisierten Methoden schreiben, das nicht threadsicher ist, abhängig davon, was Ihre Klasse tut).
Was den anderen Antworten fehlt, ist ein wichtiger Aspekt: Gedächtnisbarrieren . Die Thread-Synchronisation besteht im Wesentlichen aus zwei Teilen: Serialisierung und Sichtbarkeit. Ich rate jedem, nach "jvm memory barriere" zu googeln, da dies ein nicht triviales und äußerst wichtiges Thema ist (wenn Sie gemeinsam genutzte Daten ändern, auf die mehrere Threads zugreifen). Nachdem dies geschehen ist, empfehle ich, die Klassen des Pakets java.util.concurrent zu betrachten, um die Verwendung einer expliziten Synchronisierung zu vermeiden, was wiederum dazu beiträgt, Programme einfach und effizient zu halten und möglicherweise sogar Deadlocks zu verhindern.
Ein solches Beispiel ist ConcurrentLinkedDeque . Zusammen mit dem Befehlsmuster können hocheffiziente Arbeitsthreads erstellt werden, indem die Befehle in die gleichzeitige Warteschlange eingefügt werden - keine explizite Synchronisierung erforderlich, keine Deadlocks möglich, kein expliziter sleep () erforderlich, einfach die Warteschlange durch Aufrufen von take () abfragen.
Kurz gesagt: "Speichersynchronisation" geschieht implizit, wenn Sie einen Thread starten, ein Thread endet, Sie eine flüchtige Variable lesen, einen Monitor entsperren (einen synchronisierten Block / eine synchronisierte Funktion verlassen) usw. Diese "Synchronisation" wirkt sich (in gewissem Sinne "auf" Flushes "aus ") alle Schreibvorgänge, die vor dieser bestimmten Aktion ausgeführt wurden. Im Fall der oben genannten ConcurrentLinkedDeque "sagt" die Dokumentation:
Speicherkonsistenzeffekte: Wie bei anderen gleichzeitigen Sammlungen werden Aktionen in einem Thread vor dem Platzieren eines Objekts in einer ConcurrentLinkedDeque ausgeführt , bevor Aktionen nach dem Zugriff oder Entfernen dieses Elements aus der ConcurrentLinkedDeque in einem anderen Thread ausgeführt werden.
Dieses implizite Verhalten ist ein etwas schädlicher Aspekt, da die meisten Java-Programmierer ohne viel Erfahrung aufgrund dessen nur eine Menge nehmen, wie angegeben. Und dann stolpern Sie plötzlich über diesen Thread, nachdem Java nicht das getan hat, was es in der Produktion "tun" soll, wo es eine andere Arbeitslast gibt - und es ziemlich schwierig ist, Parallelitätsprobleme zu testen.
Synchronisiert bedeutet einfach, dass mehrere Threads, wenn sie einem einzelnen Objekt zugeordnet sind, ein fehlerhaftes Lesen und Schreiben verhindern können, wenn für ein bestimmtes Objekt ein synchronisierter Block verwendet wird. Um Ihnen mehr Klarheit zu geben, nehmen wir ein Beispiel:
class MyRunnable implements Runnable {
int var = 10;
@Override
public void run() {
call();
}
public void call() {
synchronized (this) {
for (int i = 0; i < 4; i++) {
var++;
System.out.println("Current Thread " + Thread.currentThread().getName() + " var value "+var);
}
}
}
}
public class MutlipleThreadsRunnable {
public static void main(String[] args) {
MyRunnable runnable1 = new MyRunnable();
MyRunnable runnable2 = new MyRunnable();
Thread t1 = new Thread(runnable1);
t1.setName("Thread -1");
Thread t2 = new Thread(runnable2);
t2.setName("Thread -2");
Thread t3 = new Thread(runnable1);
t3.setName("Thread -3");
t1.start();
t2.start();
t3.start();
}
}
Wir haben zwei MyRunnable-Klassenobjekte erstellt: runnable1 wird für Thread 1 und Thread 3 freigegeben, und runnable2 wird nur für Thread 2 freigegeben. Wenn nun t1 und t3 ohne Synchronisation gestartet werden, wird eine PFB-Ausgabe ausgegeben, die darauf hindeutet, dass beide Threads 1 und 3 gleichzeitig den var-Wert beeinflussen, wobei var für Thread 2 einen eigenen Speicher hat.
Without Synchronized keyword
Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -2 var value 12
Current Thread Thread -2 var value 13
Current Thread Thread -2 var value 14
Current Thread Thread -1 var value 12
Current Thread Thread -3 var value 13
Current Thread Thread -3 var value 15
Current Thread Thread -1 var value 14
Current Thread Thread -1 var value 17
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 18
Bei Verwendung von Synchronzied wartet Thread 3 in allen Szenarien darauf, dass Thread 1 abgeschlossen ist. Es wurden zwei Sperren erworben, eine für runnable1, die von Thread 1 und Thread 3 gemeinsam genutzt wird, und eine für runnable2, die nur von Thread 2 gemeinsam genutzt wird.
Current Thread Thread -1 var value 11
Current Thread Thread -2 var value 11
Current Thread Thread -1 var value 12
Current Thread Thread -2 var value 12
Current Thread Thread -1 var value 13
Current Thread Thread -2 var value 13
Current Thread Thread -1 var value 14
Current Thread Thread -2 var value 14
Current Thread Thread -3 var value 15
Current Thread Thread -3 var value 16
Current Thread Thread -3 var value 17
Current Thread Thread -3 var value 18
Einfach synchronisiert bedeutet, dass keine zwei Threads gleichzeitig auf den Block / die Methode zugreifen können. Wenn wir sagen, dass ein Block / eine Methode einer Klasse synchronisiert ist, bedeutet dies, dass jeweils nur ein Thread auf sie zugreifen kann. Intern nimmt der Thread, der zuerst versucht, darauf zuzugreifen, eine Sperre für dieses Objekt auf. Solange diese Sperre nicht verfügbar ist, kann kein anderer Thread auf eine der synchronisierten Methoden / Blöcke dieser Instanz der Klasse zugreifen.
Beachten Sie, dass ein anderer Thread auf eine Methode desselben Objekts zugreifen kann, die nicht für die Synchronisierung definiert ist. Ein Thread kann die Sperre durch Aufrufen aufheben
Object.wait()
synchronized
Block in Java ist ein Monitor im Multithreading. synchronized
Block mit demselben Objekt / derselben Klasse kann nur von einem einzelnen Thread ausgeführt werden, alle anderen warten. Dies kann hilfreich sein race condition
, wenn mehrere Threads versuchen, dieselbe Variable zu aktualisieren (der erste Schritt ist die Verwendung von volatile
Info ).
Java 5
erweitert synchronized
durch die Unterstützung von happens-before
[About]
Ein Entsperren (synchronisierter Block oder Methodenausgang) eines Monitors erfolgt vor jeder nachfolgenden Sperre (synchronisierter Block oder Methodeneintrag) desselben Monitors.
Der nächste Schritt ist java.util.concurrent