Java Synchronized Block für .class

102

Was bedeutet dieser Java-Code? Wird es alle Objekte von sperren MyClass?

synchronized(MyClass.class) {
   //is all objects of MyClass are thread-safe now ??
}

Und wie unterscheidet sich der obige Code von diesem:

synchronized(this) {
   //is all objects of MyClass are thread-safe now ??
}
Andrew Tobilko
quelle
Siehe auch
finnw

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.

Thomas Jung
quelle
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
}
Jorn
quelle
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!

David M.
quelle
1
Ja, MyClass.class kann eine beliebige statische Variable sein und den gleichen Effekt haben.
Pstanton