Zweimal auf dasselbe Objekt synchronisieren?

Lesezeit: 4 Minuten

Benutzer-Avatar
Omar Kooheji

Ich habe mich gefragt, ob ich in Java ein seltsames Verhalten bekommen würde, wenn ich zweimal dasselbe Objekt synchronisiere?

Das Szenario ist wie folgt

pulbic class SillyClassName {

    object moo;
    ...
    public void method1(){
        synchronized(moo)
        {
            ....
            method2();
            ....
        }
    }

    public void method2(){
        synchronized(moo)
        {
            doStuff();
        }
    }
}

Beide Methoden verwenden das Objekt und werden darauf synchronisiert. Wird die zweite Methode gestoppt, wenn sie von der ersten Methode aufgerufen wird, weil sie gesperrt ist?

Ich glaube nicht, weil es sich um denselben Thread handelt, aber ich bin mir nicht sicher, ob andere seltsame Ergebnisse auftreten könnten.

  • Ich frage mich, was passieren würde, wenn Methode 2 nicht von Methode 1 aufgerufen wird und wenn Methode 1 und 2 gleichzeitig von beispielsweise Objekt 1 und 2 aufgerufen werden werden diese beiden Methoden gleichzeitig ausgeführt?

    – Benutzer3366706

    17. Oktober 2018 um 20:28 Uhr

Benutzer-Avatar
Leigh

Wiedereintritt

Verwendung von synchronisierten Blöcken wiedereintretend locks, was bedeutet, wenn der Thread die Sperre bereits hält, kann er sie ohne Probleme erneut erwerben. Daher wird Ihr Code wie erwartet funktionieren.

Siehe unten Java-Tutorial Seite Intrinsische Sperren und Synchronisation.

Stand 2015-01 zu zitieren…

Reentrante Synchronisierung

Denken Sie daran, dass ein Thread keine Sperre erwerben kann, die einem anderen Thread gehört. Aber ein Thread kann eine Sperre erwerben, die er bereits besitzt. Wenn Sie einem Thread erlauben, dieselbe Sperre mehr als einmal zu erwerben, wird dies aktiviert ablaufinvariante Synchronisierung. Dies beschreibt eine Situation, in der synchronisierter Code direkt oder indirekt eine Methode aufruft, die auch synchronisierten Code enthält, und beide Codesätze dieselbe Sperre verwenden. Ohne ablaufinvariante Synchronisierung müsste synchronisierter Code viele zusätzliche Vorkehrungen treffen, um zu vermeiden, dass ein Thread sich selbst blockiert.

Benutzer-Avatar
Praveen Mookoni

Ich denke, wir müssen für das, was Sie versuchen, eine reentrante Sperre verwenden. Hier ein Ausschnitt aus http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/ReentrantLock.html.

Was verstehen wir unter einer reentranten Sperre? Einfach, dass der Sperre eine Erwerbszählung zugeordnet ist, und wenn ein Thread, der die Sperre hält, sie erneut erwirbt, wird die Erwerbszählung erhöht und die Sperre muss dann zweimal freigegeben werden, um die Sperre wirklich freizugeben. Dies entspricht der Semantik von synchronisiert; Wenn ein Thread in einen synchronisierten Block eintritt, der durch einen Monitor geschützt ist, den der Thread bereits besitzt, darf der Thread fortfahren, und die Sperre wird nicht aufgehoben, wenn der Thread den zweiten (oder nachfolgenden) synchronisierten Block verlässt, sondern wird nur freigegeben wenn es den ersten synchronisierten Block verlässt, in den es geschützt durch diesen Monitor eingetreten ist.

Obwohl ich es nicht ausprobiert habe, denke ich, wenn Sie das tun möchten, was Sie oben haben, müssen Sie eine wiedereintrittsfähige Sperre verwenden.

Java scheint verschachtelte Sperren auf einem Objekt durch denselben Thread vollständig zu unterstützen. Das bedeutet, wenn ein Thread eine äußere und eine innere Sperre für ein Objekt hat und ein anderer Thread versucht, dasselbe Objekt zu sperren, wird der zweite Thread ausgesetzt, bis beide Sperren wurden vom ersten Thread freigegeben.

Meine Tests wurden unter Java 6 SE durchgeführt.

  • In verschachtelten synchronisierten Blöcken wird nur eine Sperre von demselben Thread erworben.

    – Akash5288

    26. Juni 2014 um 18:02 Uhr

Keine Probleme. In Ihrem Beispiel (sobald Sie Ihren Code korrigiert haben, um die Kompilierungswarnungen zu beseitigen, die Sie erhalten 😉 ), stellt die Synchronisierung sicher, dass die Blöcke in Methode1 und Methode2 nicht gleichzeitig ausgeführt werden.

Das ist sozusagen der Synchronisationspunkt. 🙂


Bearbeiten: Sorry, verpasste Teile Ihrer Frage, aber Phill hat sie beantwortet. Zusammenfassend lässt sich sagen, dass sich ein einzelner Thread nicht selbst blockieren kann.

In Java ist die synchronized Das Schlüsselwort für eine Methode wird im Grunde mit dem aktuellen Objekt synchronisiert, sodass es im Grunde implizit das tut, was Sie oben vorgeschlagen haben.

Sie werden keine Probleme mit der Synchronisierung eines Objekts in einer Methode und der anschließenden Synchronisierung desselben Objekts in einer anderen Methode haben, da, wie Sie sagen, der aktuelle Thread bereits die Sperre für dieses Objekt hält.

Benutzer-Avatar
fospathi

Nein, die zweite Methode wird nicht beendet, wenn sie von der ersten aufgerufen wird. Es treten keine seltsamen Ergebnisse auf (außer einem leichten Overhead für die Überprüfung der Sperre. Dies spielt keine große Rolle. Ab Java 6 haben Sie in der JVM eine Sperrvergröberung – Whitepaper zur Leistung von Java SE 6.)

Sehen Sie sich zum Beispiel den Quellcode von java.util.Vector an. Es gibt viele Aufrufe anderer synchronisierter Methoden aus synchronisierten Methoden heraus.

1039670cookie-checkZweimal auf dasselbe Objekt synchronisieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy