Java Synchronized Block für .class


Antworten:


144

Das Snippet synchronized(X.class)verwendet die Klasseninstanz als Monitor. Da es nur eine Klasseninstanz gibt (das Objekt, das die Klassenmetadaten zur Laufzeit darstellt), kann sich ein Thread in diesem Block befinden.

Mit synchronized(this)dem Block wird von der Instanz geschützt. Für jede Instanz darf nur ein Thread in den Block eintreten.

synchronized(X.class)wird verwendet, um sicherzustellen, dass sich genau ein Thread im Block befindet. synchronized(this)stellt sicher, dass es genau einen Thread pro Instanz gibt. Ob dies den tatsächlichen Code im Block threadsicher macht, hängt von der Implementierung ab. Wenn mutieren, reicht nur der Status der Instanz synchronized(this)aus.


6
"Es können so viele Threads in den Block eintreten, wie Instanzen vorhanden sind" impliziert, dass die zweite Form als Semaphor fungiert, was nicht wahr ist. Sie sollten etwas sagen wie: "synchronisiert (dies) stellt sicher, dass nur ein Thread den Block für eine bestimmte Instanz der Klasse betreten kann".
liwp

Korrigiert. Das wollte ich sagen.
Thomas Jung

2
Was ist die Klasseninstanz gegenüber der Instanz?
Weishi Zeng

Wenn Sie also eine statische Methode haben und nicht den gesamten Körper synchronisieren möchten, ist die Synchronisierung (dies) nicht gut, stattdessen ist die Synchronisierung (Foo.class) angemessen. Ist das richtig?
krupal.agile

84

So ergänzen Sie die anderen Antworten:

static void myMethod() {
  synchronized(MyClass.class) {
    //code
  }
}

ist äquivalent zu

static synchronized void myMethod() {
  //code
}

und

void myMethod() {
  synchronized(this) {
    //code
  }
}

ist äquivalent zu

synchronized void myMethod() {
  //code
}

12
Ich brauchte eine zweite Lesung, um festzustellen, dass die ersten beiden Beispiele das Schlüsselwort "static" haben. Ich möchte nur andere darauf hinweisen, die dies vielleicht gesehen und verpasst haben. Ohne das statische Schlüsselwort wären die ersten beiden Beispiele nicht identisch.
Kurtzbot

1
Diese Beispiele sind NICHT gleichwertig! Die synchronisierten Methoden werden als Loch "synchronisiert", wenn ein Thread versucht, die Methoden aufzurufen. Die Blöcke hingegen können darüber und darunter Code enthalten, der von mehreren Threads ausgeführt werden kann. Sie synchronisieren nur innerhalb des Blocks! Das ist nicht dasselbe!
JacksOnF1re

public static Singleton getInstance () {if (instance == null) {synchronized (Singleton.class) {instance = new Singleton (); }} return instance; }
JacksOnF1re

2
Der springende Punkt ist , dass es ist kein Code außerhalb der synchronizedBlöcke. Das macht sie gleichwertig. Wenn Sie ein Beispiel ändern, sind sie tatsächlich nicht mehr dieselben.
Jorn

22

Nein, der erste erhält eine Sperre für die Klassendefinition von MyClass, nicht für alle Instanzen davon. Bei Verwendung in einer Instanz werden jedoch alle anderen Instanzen effektiv blockiert, da sie eine einzige Klassendefinition verwenden.

Der zweite wird nur für die aktuelle Instanz gesperrt.

Ob dies den Thread Ihrer Objekte sicher macht, ist eine weitaus komplexere Frage - wir müssten Ihren Code sehen!


1
Ja, MyClass.class kann eine beliebige statische Variable sein und den gleichen Effekt haben.
Pstanton
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.