Wenn ich zwei Methoden in derselben Klasse synchronisiert habe, können sie dann gleichzeitig auf demselben Objekt ausgeführt werden ? beispielsweise:
class A {
public synchronized void methodA() {
//method A
}
public synchronized void methodB() {
// method B
}
}
Ich weiß, dass ich nicht methodA()
zweimal auf demselben Objekt in zwei verschiedenen Threads ausgeführt werden kann. das Gleiche in methodB()
.
Aber kann ich methodB()
auf einem anderen Thread laufen, während er methodA()
noch läuft? (gleiches Objekt)
obj.methodB()
ist gleichbedeutend mitA.methodB()
wannmethodB()
iststatic
. Daher ja, sie blockieren (auf dem Monitor der Klasse, nicht des Objekts)..class
Objektsperre verwenden. Also wenn du hastclass A {static synchronized void m() {} }
. Und dann ruft ein Thread auf, dassnew A().m()
er die Sperre erhältnew A()
Objekt . Wenn dann ruft ein anderer ThreadA.m()
es DAS VERFAHREN KEIN PROBLEM TRITT weil das, was es sieht für Sperre aktiviert istA.class
Objekt , während NO THREADS diese Art der Sperre besitzen . Also auch wenn Sie Methode deklariertsynchronized
es actualy zugegriffen wird von zwei verschiedenen Threads ZUGLEICH . Also: Verwenden Sie niemals Objektreferenzen, um statische MethodenIm Beispiel sind Methode A und Methode B Instanzmethoden (im Gegensatz zu statischen Methoden). Putten
synchronized
einer Instanzmethode bedeutet, dass der Thread die Sperre (die "intrinsische Sperre") für die Objektinstanz erwerben muss, für die die Methode aufgerufen wird, bevor der Thread mit der Ausführung von Code in dieser Methode beginnen kann.Wenn zwei verschiedene Instanzmethoden als synchronisiert markiert sind und verschiedene Threads diese Methoden gleichzeitig für dasselbe Objekt aufrufen, kämpfen diese Threads um dieselbe Sperre. Sobald ein Thread die Sperre erhält, werden alle anderen Threads von allen synchronisierten Instanzmethoden für dieses Objekt ausgeschlossen.
Damit die beiden Methoden gleichzeitig ausgeführt werden können, müssten sie unterschiedliche Sperren verwenden:
Dabei ermöglicht die synchronisierte Blocksyntax die Angabe eines bestimmten Objekts, für das der ausführende Thread die intrinsische Sperre erhalten muss, um in den Block einzutreten.
Es ist wichtig zu verstehen, dass, obwohl wir einzelne Methoden mit einem "synchronisierten" Schlüsselwort versehen, das Kernkonzept die intrinsische Sperre hinter den Kulissen ist.
So beschreibt das Java-Tutorial die Beziehung:
Der Zweck des Sperren besteht darin, gemeinsam genutzte Daten zu schützen. Sie würden separate Sperren verwenden, wie im obigen Beispielcode gezeigt, nur wenn jede Sperre unterschiedliche Datenelemente schützt.
quelle
static synchronized
odersynchronized (A.class)
Java Thread erwirbt eine Sperre auf Objektebene, wenn es in eine instanzsynchronisierte Java-Methode eingeht , und eine Sperre auf Klassenebene, wenn es in eine statische synchronisierte Java-Methode eingeht .
In Ihrem Fall gehören die Methoden (Instanzen) zur selben Klasse. Wenn also ein Thread in eine mit Java synchronisierte Methode oder einen Block eintritt, erhält er eine Sperre (das Objekt, für das die Methode aufgerufen wird). Daher kann eine andere Methode nicht gleichzeitig für dasselbe Objekt aufgerufen werden, bis die erste Methode abgeschlossen und die Sperre (für das Objekt) aufgehoben wurde.
quelle
private final Object lock = new object();
mit synchronisiert verwenden, damit nur ein Thread eine der beiden Methoden ausführen kann? Vielen DankIn Ihrem Fall haben Sie zwei Methoden auf derselben Klasseninstanz synchronisiert. Daher können diese beiden Methoden nicht gleichzeitig auf verschiedenen Threads derselben Instanz der Klasse A ausgeführt werden. Sie können jedoch auf verschiedenen Instanzen der Klasse A ausgeführt werden.
ist das gleiche wie:
quelle
private final Object lock = new Object();
und sie jetztlock
mit synchronisiertem Block in zwei Methoden verwende? Gilt Ihre Aussage dann? IMO, da Object die übergeordnete Klasse aller Objekte ist. Selbst wenn sich die Threads auf einer anderen Instanz der Klasse befinden, kann jeweils nur einer auf den Code innerhalb des synchronisierten Blocks zugreifen. Vielen Dank.Aus der Orakel-Dokumentation Link
Das Synchronisieren von Methoden hat zwei Auswirkungen:
Dies beantwortet Ihre Frage: Für dasselbe Objekt können Sie keine zweite synchronisierte Methode aufrufen, wenn die erste synchronisierte Methodenausführung ausgeführt wird.
Schauen Sie sich diese Dokumentation an Seite intrinsische Sperren und Sperrverhalten zu verstehen.
quelle
Stellen Sie sich Ihren Code wie folgt vor:
Auf Methodenebene synchronisiert bedeutet also einfach synchronisiert (dies). Wenn ein Thread eine Methode dieser Klasse ausführt, erhält er die Sperre vor dem Start der Ausführung und hält sie, bis die Ausführung der Methode abgeschlossen ist.
In der Tat ist es nicht möglich!
Daher können mehrere Threads nicht mehrere synchronisierte Methoden gleichzeitig für dasselbe Objekt ausführen.
quelle
Aus Gründen der Klarheit ist es möglich, dass sowohl statisch synchronisierte als auch nicht statisch synchronisierte Methoden gleichzeitig oder gleichzeitig ausgeführt werden können, da eine Sperre auf Objektebene und eine Sperre auf Klassenebene vorhanden ist.
quelle
Die Schlüsselidee bei der Synchronisierung, die sich nicht leicht einfügt, ist, dass sie nur dann wirksam wird, wenn Methoden für dasselbe Objekt aufgerufen werden - dies wurde bereits in den Antworten und Kommentaren hervorgehoben.
Das folgende Beispielprogramm soll das gleiche klar bestimmen -
Beachten Sie den Unterschied in der Ausgabe, wie der gleichzeitige Zugriff wie erwartet zulässig ist wenn Methoden für verschiedene Objektinstanzen aufgerufen werden.
Ausgabe mit noEffectOfSynchronizedAsMethodsCalledOnDifferentObjects () kommentiert - die Ausgabe erfolgt in der Reihenfolge methodA in> methodA Out .. methodB in> methodB Out
und Ausgabe mit synchronizedEffectiveAsMethodsCalledOnSameObject () kommentiert - die Ausgabe zeigt den gleichzeitigen Zugriff von Methode1 durch Thread1 und Thread0 im hervorgehobenen Abschnitt -
Wenn Sie die Anzahl der Threads erhöhen, wird dies noch deutlicher.
quelle
Nein, es ist nicht möglich, wenn es möglich wäre, könnten beide Methoden dieselbe Variable gleichzeitig aktualisieren, was die Daten leicht beschädigen könnte.
quelle
Ja, sie können beide Threads gleichzeitig ausführen. Wenn Sie 2 Objekte der Klasse erstellen, da jedes Objekt nur eine Sperre enthält und jede synchronisierte Methode eine Sperre erfordert. Wenn Sie also gleichzeitig ausgeführt werden möchten, erstellen Sie zwei Objekte und versuchen Sie dann, diese Objektreferenz zu verwenden.
quelle
Sie synchronisieren es für ein Objekt, nicht für eine Klasse. Sie können also nicht gleichzeitig auf demselben Objekt ausgeführt werden
quelle
Zwei verschiedene Threads, die eine gemeinsame synchronisierte Methode für das einzelne Objekt ausführen. Da das Objekt dasselbe ist und ein Thread es mit einer synchronisierten Methode verwendet, muss die Sperre geändert werden. Wenn die Sperre aktiviert ist, wird dieser Thread in den Wartezustand versetzt. Wenn die Sperre deaktiviert ist, kann sie auf das Objekt zugreifen. Wenn sie darauf zugreift, wird die Sperre aktiviert und die Sperre wird erst freigegeben, wenn die Ausführung abgeschlossen ist. Wenn der andere Thread eintrifft, wird die Sperre geändert, da sie aktiviert ist. Sie wartet, bis der erste Thread seine Ausführung abgeschlossen hat, und gibt die Sperre für das Objekt frei. Sobald die Sperre aufgehoben wird, erhält der zweite Thread Zugriff auf das Objekt und Dadurch wird die Sperre aktiviert, bis sie ausgeführt wird. Damit die Ausführung nicht gleichzeitig erfolgt, werden beide Threads einzeln ausgeführt.
quelle