Sie sind in ihrer Funktion äquivalent, obwohl die Compiler, die ich getestet habe (Java 1.6.0_07 und Eclipse 3.4), unterschiedliche Bytecodes erzeugen. Der erste generiert:
%Vor%Die zweite erzeugt:
%Vor%(Danke an ASM für den Bytecode-Druck).
Der Unterschied zwischen ihnen besteht also weiterhin auf der Bytecode-Ebene, und es liegt an der JVM, ihr Verhalten gleich zu machen. Sie haben jedoch den gleichen funktionalen Effekt - siehe Beispiel in der Java-Sprachspezifikation.
Es sollte beachtet werden, dass, wenn die Methode in einer Unterklasse außer Kraft gesetzt wird, sie nicht notwendigerweise synchronisiert ist - also gibt es auch keinen Unterschied in dieser Hinsicht.
Ich habe auch einen Test ausgeführt, um einen Thread zu blockieren, der in jedem Fall versucht, auf den Monitor zuzugreifen, um zu vergleichen, wie seine Stack-Traces in einem Thread-Dump aussehen würden, und beide enthalten die fragliche Methode.
Ich habe den ursprünglichen Kommentar gemacht, dass die Aussagen identisch sind.
In beiden Fällen ist das erste, was passiert, dass der aufrufende Thread versucht, den Monitor des aktuellen Objekts (dh this
') zu erfassen.
Ich weiß nicht über verschiedene Bytecode, ich bin glücklich, den Unterschied zu hören. Aber in der Praxis sind sie zu 100% identisch.
BEARBEITEN: Ich werde das klären, da einige Leute hier falsch lagen. Überlegen Sie:
%Vor% In diesem Fall überschreibt doStuff()
in Klasse B weiterhin doStuff()
in Klasse A, obwohl es nicht synchronisiert ist.
Synchronisiertes Schlüsselwort ist niemals Teil des Vertrags! Nicht für Unterklassen, nicht für Schnittstellen, nicht für abstrakte Klassen.
Ich habe den ursprünglichen Kommentar gemacht. Mein Kommentar war, dass sie logisch gleichwertig sind, aber zu verschiedenen Bytecode kompilieren.
Ich habe nichts hinzugefügt, um es zu dieser Zeit zu rechtfertigen, weil es nicht viel zu rechtfertigen gibt - sie tun nur zu einem anderen Bytecode. Wenn Sie eine Methode als synchronized deklarieren, ist diese Synchronisation Teil der Definition der Methode. Ein synchronisierter Block innerhalb einer Methode ist kein Teil der Methodendefinition , sondern beinhaltet separate Bytecodes zum Erfassen und Freigeben des Monitors, wie eines der obigen Poster gezeigt hat. Streng genommen sind das etwas unterschiedliche Dinge, obwohl für die Gesamtlogik Ihres Programms gleichwertig sind. . .
Wann ist das wichtig? Nun, auf den meisten modernen Desktop-VMs kaum. Aber zum Beispiel:
Ja. Wenn Sie das synchronisierte Schlüsselwort für eine Instanzmethode verwenden, wird 'this' als Monitor verwendet. Wenn Sie es für eine Klassenmethode verwenden (statische Methode), wird die Klasse 'Class object (Foo.class)' verwendet.
Auf diese Weise können Sie ganze Methoden synchronisieren und gleichzeitig mit einem Code-Snippet in einer anderen Methode synchronisieren, indem Sie den synchronisierten Blockstil verwenden.
Sie sind in ihrer Funktion nicht ganz gleichwertig. Anderer Code könnte Reflektion verwenden, um zu sehen, ob Ihre Methode den synchronisierten Modifikator hat, aber es gibt keine Möglichkeit festzustellen, ob eine Methode einen synchronisierten Block enthält, ohne dessen Bytecode zu lesen.
Die Möglichkeit zu bestimmen, ob eine Methode gelegentlich synchronisiert wird, ist praktisch. Persönlich habe ich dieses Flag verwendet, um eine redundante Sperrung bei der Synchronisierung bei der aspektorientierten Programmierung zu vermeiden.
In diesem Fall:
someMethod
blockiert die gesamte Klasse someMethodA
blocks myObjectA
only someMethodB
blocks myObjectB
only someMethodA
und someMethodB
können gleichzeitig aufgerufen werden Tags und Links java synchronization