In Java 8 kann ich leicht schreiben:
interface Interface1 {
default void method1() {
synchronized (this) {
// Something
}
}
static void method2() {
synchronized (Interface1.class) {
// Something
}
}
}
Ich werde die vollständige Synchronisationssemantik erhalten, die ich auch in Klassen verwenden kann. Ich kann den synchronized
Modifikator jedoch nicht für Methodendeklarationen verwenden:
interface Interface2 {
default synchronized void method1() {
// ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
}
static synchronized void method2() {
// ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here
}
}
Nun kann man argumentieren , dass die beiden Schnittstellen verhalten sich die gleiche Weise , außer dass Interface2
ein legt Vertrag auf method1()
und auf method2()
, die ein wenig stärker als das , was der Interface1
Fall ist. Natürlich könnten wir auch argumentieren, dass default
Implementierungen keine Annahmen über den konkreten Implementierungsstatus treffen sollten oder dass ein solches Schlüsselwort einfach nicht an Bedeutung gewinnen würde.
Frage:
Was ist der Grund, warum die JSR-335-Expertengruppe beschlossen hat, synchronized
Schnittstellenmethoden nicht zu unterstützen ?
quelle
default synchronized
, aber nicht unbedingt fürstatic synchronized
, obwohl ich akzeptieren würde, dass letzteres aus Konsistenzgründen weggelassen worden sein könnte.synchronized
Modifikator in Unterklassen möglicherweise überschrieben wird. Daher wäre es nur wichtig, wenn es etwas als endgültige Standardmethode gäbe. (Ihre andere Frage)synchronized
in Superklassen deklariert sind, wodurch die Synchronisation effektiv entfernt wird. Es würde mich nicht wundern , wenn nicht unterstütztsynchronized
und nicht unterstütztfinal
wird, möglicherweise aufgrund von Mehrfachvererbung (z. B. Vererbungvoid x()
undsynchronized void x()
usw.). Aber das ist Spekulation. Ich bin neugierig auf einen maßgeblichen Grund, falls es einen gibt.super
was eine vollständige Neuimplementierung und einen möglichen Zugriff auf private Mitglieder erfordert. Übrigens gibt es einen Grund, warum diese Methoden als "Verteidiger" bezeichnet werden - sie sind vorhanden, um das Hinzufügen neuer Methoden zu erleichtern.Antworten:
Während es auf den ersten Blick offensichtlich erscheint, dass man den
synchronized
Modifikator bei Standardmethoden unterstützen möchte , stellt sich heraus, dass dies gefährlich wäre und daher verboten war.Synchronisierte Methoden sind eine Abkürzung für eine Methode, die sich so verhält, als ob der gesamte Körper in einem
synchronized
Block eingeschlossen ist, dessen Sperrobjekt der Empfänger ist. Es mag sinnvoll erscheinen, diese Semantik auch auf Standardmethoden auszudehnen. Schließlich handelt es sich auch um Instanzmethoden mit einem Empfänger. (Beachten Sie, dasssynchronized
Methoden vollständig eine syntaktische Optimierung sind; sie werden nicht benötigt, sie sind nur kompakter als der entsprechendesynchronized
Block. Es gibt ein vernünftiges Argument dafür, dass dies in erster Linie eine vorzeitige syntaktische Optimierung war und dass Methoden synchronisiert wurden verursachen mehr Probleme als sie lösen, aber dieses Schiff ist vor langer Zeit gesegelt.)Warum sind sie gefährlich? Bei der Synchronisierung geht es um das Sperren. Beim Sperren geht es darum, den gemeinsamen Zugriff auf den veränderlichen Status zu koordinieren. Jedes Objekt sollte über eine Synchronisationsrichtlinie verfügen, die bestimmt, welche Sperren welche Statusvariablen schützen. (Siehe Java-Parallelität in der Praxis , Abschnitt 2.4.)
Viele Objekte verwenden als Synchronisationsrichtlinie das Java Monitor Pattern (JCiP 4.1), bei dem der Status eines Objekts durch seine interne Sperre geschützt wird. Dieses Muster hat nichts Magisches oder Besonderes, aber es ist praktisch, und die Verwendung des
synchronized
Schlüsselworts für Methoden setzt implizit dieses Muster voraus.Es ist die Klasse, die den Status besitzt, der die Synchronisierungsrichtlinie dieses Objekts bestimmen kann. Schnittstellen besitzen jedoch nicht den Status der Objekte, in die sie eingemischt sind. Die Verwendung einer synchronisierten Methode in einer Schnittstelle setzt daher eine bestimmte Synchronisierungsrichtlinie voraus, für die Sie jedoch keine vernünftige Grundlage haben. Dies kann durchaus der Fall sein Die Verwendung der Synchronisierung bietet keinerlei zusätzliche Thread-Sicherheit (möglicherweise synchronisieren Sie mit der falschen Sperre). Dies würde Ihnen das falsche Gefühl des Vertrauens geben, dass Sie etwas gegen die Thread-Sicherheit unternommen haben, und keine Fehlermeldung sagt Ihnen, dass Sie die falsche Synchronisierungsrichtlinie annehmen.
Es ist bereits schwierig genug, eine Synchronisierungsrichtlinie für eine einzelne Quelldatei konsistent zu verwalten. Es ist noch schwieriger sicherzustellen, dass eine Unterklasse die von ihrer Oberklasse definierte Synchronisationsrichtlinie korrekt einhält. Der Versuch, dies zwischen solchen lose gekoppelten Klassen (einer Schnittstelle und den möglicherweise vielen Klassen, die sie implementieren) zu tun, wäre nahezu unmöglich und sehr fehleranfällig.
Wofür wäre das Argument angesichts all dieser Argumente? Es scheint, dass es hauptsächlich darum geht, dass sich Schnittstellen eher wie Merkmale verhalten. Während dies ein verständlicher Wunsch ist, ist das Design Center für Standardmethoden die Schnittstellenentwicklung, nicht "Traits--". Wo die beiden konsequent erreicht werden konnten, haben wir uns bemüht, aber wo einer im Konflikt mit dem anderen steht, mussten wir uns für das primäre Designziel entscheiden.
quelle
synchronized
Methodenmodifikator in der Javadoc-Ausgabe angezeigt wurde, was die Leute irreführte, zu glauben, dass er Teil der Spezifikation war. Dies wurde in JDK 1.2 behoben. Selbst wenn es auf einer öffentlichen Methode angezeigt wird, ist dersynchronized
Modifikator Teil der Implementierung und nicht des Vertrags. (Ähnliche Überlegungen und Behandlungen fanden für dennative
Modifikator statt.)synchronized
und sichere Komponenten einzufädeln, und Sie hatten ein fast thread-sicheres Programm. Das Problem war, dass dies normalerweise in Ordnung funktionierte, aber auf überraschende und spröde Weise kaputt ging. Ich bin damit einverstanden, dass das Verständnis der Funktionsweise Ihrer Sperre ein Schlüssel für robuste Anwendungen ist.synchronized(this) {...}
einedefault
Methode erlaubt ? (Wie in Lukas 'Frage gezeigt.) Erlaubt das nicht, dass die Standardmethode auch den Status der Implementierungsklasse besitzt? Wollen wir das nicht auch verhindern? Benötigen wir eine FindBugs-Regel, um die Fälle zu finden, für die nicht informierte Entwickler dies tun?synchronized(vector)
. Wenn Sie sicher sein möchten, sollten Sie niemals ein öffentliches Objekt (wie sichthis
selbst) zum Sperren verwenden.Ergebnis:
(Entschuldigung für die Verwendung der Elternklasse als Beispiel)
Aus dem Ergebnis können wir erkennen, dass die übergeordnete Klassensperre jeder Unterklasse gehört. SonSync1- und SonSync2-Objekte haben unterschiedliche Objektsperren. Jedes Schloss ist unabhängig. In diesem Fall denke ich, dass es nicht gefährlich ist, eine in einer übergeordneten Klasse synchronisierte oder eine gemeinsame Schnittstelle zu verwenden. könnte jemand mehr dazu erklären?
quelle