Frage

Was ist der Unterschied zwischen einer synchronisierten Methode und einem synchronisierten Block in Java?

Ich habe die Antwort im Netz gesucht, die Leute scheinen sich in diesem Fall so nicht sicher zu sein :-(

Meine Einstellung wäre, dass es keinen Unterschied zwischen den beiden gibt, außer dass der Synchronisationsblock im Bereich lokaler ist und daher die Schloss weniger Zeit hat?

Und bei der Schloss einer statischen Methode, was ist das Schloss aufgenommen? Was bedeutet eine Sperre für den Unterricht?

War es hilfreich?

Lösung

Eine synchronisierte Methode verwendet den Methodenempfänger als Sperre (dh this für nicht statische Methoden und die entsprechende Klasse für statische Methoden). Synchronized Blöcke verwendet den Ausdruck als Schloss.

Die folgenden zwei Methoden entsprechen also der Verriegelung von Prospekten:

synchronized void mymethod() { ... }

void mymethod() {
  synchronized (this) { ... }
}

Für statische Methoden wird die Klasse gesperrt:

class MyClass {
  synchronized static mystatic() { ... }

  static mystaticeq() {
    syncrhonized (MyClass.class) { ... }
  }
}

Für synchronisierte Blöcke können Sie alle Nichts verwendennull Objekt als Schloss:

synchronized (mymap) {
  mymap.put(..., ...);
}

Sperrumfang

Für synchronisierte Methoden wird das Schloss während des gesamten Methodenbereichs gehalten, während in der synchronized Block, das Schloss wird nur während dieses Blockbereichs gehalten (auch als kritischer Abschnitt bezeichnet). In der Praxis darf die JVM optimieren, indem einige Operationen aus dem entfernt werden synchronized Blockdurchführung, wenn es beweisen kann, dass sie sicher gemacht werden kann.

Andere Tipps

Eine synchronisierte Methode ist eine Kurzform. Dies:

class Something {
    public synchronized void doSomething() {
        ...
    }

    public static synchronized void doSomethingStatic() {
        ...
    }
}

ist in jeder Hinsicht entspricht:

class Something {
    public void doSomething() {
        synchronized(this) {
            ...
        }
    }

    public static void doSomethingStatic() {
        synchronized(Something.class) {
            ...
        }
    }
}

(Wo Something.class ist das Klassenobjekt für die Klasse Something.)

In der Tat können Sie mit einem synchronisierten Block genauer mit Ihrem Schloss und feiner darüber, wann Sie ihn verwenden möchten, genauer sein, aber ansonsten gibt es keinen Unterschied.

Ja, das ist ein Unterschied. Das andere ist, dass Sie eine Sperre für andere Objekte erwerben können als this.

Der Hauptunterschied ist: Wenn Sie eine Methode für synchronisiert deklarieren, wird der gesamte Körper der Methode synchronisiert. Wenn Sie jedoch den synchronisierten Block verwenden, können Sie nur den "kritischen Abschnitt" der Methode im synchronisierten Block umgeben, während Sie den Rest der Methode aus dem Block herauslassen.

Wenn die gesamte Methode Teil des kritischen Abschnitts ist, gibt es effektiv keinen Unterschied. Wenn dies nicht der Fall ist, sollten Sie einen synchronisierten Block nur um den kritischen Abschnitt verwenden. Je mehr Aussagen Sie in einem synchronisierten Block haben, desto weniger Gesamtparallelität erhalten Sie, sodass Sie diese auf das Minimum halten möchten.

Eine synchronisierte Methode sperrt die Objektinstanz, in der die Methode enthalten ist.

Wobei als synchronisierter Block auf jedem Objekt sperren kann - typischerweise ein als Instanzvariable definierter Mutex -Ohrfehler. Dies ermöglicht mehr Kontrolle darüber, welche Schlösser in Betrieb sind.

Meine Einstellung wäre, dass es keinen Unterschied zwischen den beiden gibt, außer dass der Synchronisationsblock im Bereich lokaler ist und daher die Schloss weniger Zeit hat?

Ja. Sie haben Recht. nicht wie synchronized Methoden, synchronisierte Aussagen müssen das Objekt angeben, das die intrinsische Sperre liefert.

Beispiel aus Java Tutorial:

public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

Synchronisierte Aussagen sind auch nützlich, um die Parallelität mit feinkörniger Synchronisation zu verbessern. Auf derselben Tutorial -Seite finden Sie ein gutes Beispiel für den folgenden Anwendungsfall.

Nehmen wir zum Beispiel an, Klasse MsLunch hat zwei Instanzfelder, C1 und C2, die nie zusammen verwendet werden. Alle Aktualisierungen dieser Felder müssen sein synchronized, Es gibt jedoch keinen Grund, zu verhindern, dass ein Update von C1 mit einem Update von C2 verschachtelt wird - und dies reduziert die Parallelität durch unnötige Blockierung. Anstatt synchronisierte Methoden zu verwenden oder auf andere Weise das damit verbundene Sperre zu verwenden, erstellen wir zwei Objekte ausschließlich, um Sperren bereitzustellen.

Und bei der Schloss einer statischen Methode, was ist das Schloss aufgenommen? Was bedeutet eine Sperre für den Unterricht?

In diesem Fall erwirbt der Thread das intrinsische Schloss für das Klassenobjekt, das der Klasse zugeordnet ist. Daher wird der Zugang zu den statischen Feldern der Klasse durch ein Schloss gesteuert, das sich für jede Instanz der Klasse vom Schloss unterscheidet.

Wenn Sie eine Methode machen als synchronisiert (non static ) :

Es ist für zwei Aufrufe von nicht möglich synchronized Methoden auf demselben Objekt zum Verschließen. Wenn ein Thread eine synchronisierte Methode für ein Objekt ausführt, werden alle anderen Threads, die synchronisierte Methoden für denselben Objektblock (Suspend -Ausführung) aufrufen, bis der erste Thread mit dem Objekt ausgeführt wird.

Wenn Sie eine Methode machen als static synchronized :

Es ist für zwei Aufrufe von nicht möglich static synchronized Methoden zu verschiedenen Objekten derselben Klasse, um zu verschieben. Wenn ein Thread a ausführt static synchronized Methode für ein Objekt der Klasse A, alle anderen Threads, die aufrufen static synchronized Methoden auf einem der Objekte des Blocks der Klasse A (Suspend Execution), bis der erste Thread mit der Methodenausführung durchgeführt wird.

In dieser SE -Frage finden Sie bessere Alternativen zur Synchronisation:

Synchronisierte (dies) in Java vermeiden?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top