2016-07-05 14 views
2

Um die Probleme und Lösungen für Parallelität in Java richtig zu verstehen, ging ich durch das offizielle Java-Tutorial. Auf einer der Seiten definierten sie Intrinsic Locks und Synchronisationlink. Auf dieser Seite sagen sie das:Was bedeutet intrinsische Sperre eigentlich für eine Java-Klasse?

Solange ein Thread eine intrinsische Sperre besitzt, kann kein anderer Thread die gleiche Sperre erwerben. Der andere Thread wird blockiert, wenn er versucht, die Sperre zu zu erlangen.

Auch erwähnen sie im Abschnitt Locks in synchronisierter Methods dass:

Wenn ein Thread eine synchronisierte Methode aufruft, automatisch es für diese Methode des Objekts und gibt die intrinsische Sperre erlangt, wenn Die Methode kehrt zurück. Die Sperrfreigabe tritt auf, selbst wenn die Rückgabe durch eine nicht abgefangene Ausnahme verursacht wurde.

für mich, dies bedeutet, dass sobald ich eine synchronisierte Methode aus einem der Fäden nennen, halte ich der intrinsischen Verriegelung des Fadens haben und da

Intrinsic Schlösser eine Rolle in beiden Aspekten spielen der Synchronisation: erzwingt den exklusiven Zugriff auf den Status eines Objekts und passiert vor Beziehungen, die für die Sichtbarkeit unerlässlich sind.

Wäre ein anderer Thread nicht in der Lage, eine andere synchronisierte Methode derselben Klasse aufzurufen? Wenn ja, dann ist der ganze Zweck der synchronisierten Methoden besiegt. Ist es nicht?

+0

Ihre Frage ist mehrdeutig. Worauf bezieht sich "Ich", wenn Sie fragen: "Wäre ich nicht in der Lage, eine andere synchronisierte Methode aufzurufen ..."? Rahmen Sie Ihre Frage in Bezug auf Threads. Fragen Sie, ob der gleiche Thread eine synchronisierte Methode von einer synchronisierten Methode aufrufen kann? D.h., sind Java-Intrinsic-Locks reentrant? Oder fragst du den Nutzen eines Mutex? – erickson

+0

Intrinsic-Methode bedeutet, dass Sie kein Objekt zum Synchronisieren Ihrer Methoden erstellen müssen. Im Vergleich dazu können Sie eine extrinsische Sperre verwenden, indem Sie 'synchronized (myLock) {...}' aufrufen. Dies ist ein Auszug aus dem Buch Java Concurrency in der Praxis: "Die Tatsache, dass jedes Objekt eine integrierte Sperre hat, ist nur eine Annehmlichkeit, so dass Sie nicht explizit Sperrobjekte erstellen müssen" –

+0

Ich habe gerade die Frage aktualisiert, um die erwähnte Mehrdeutigkeit zu verdeutlichen von der @erickson .. – Swapnil

Antwort

2

Also nur um meinen Kommentar oben als Antwort zu wiederholen. Intrinsic Locking bedeutet, dass Sie kein Objekt zum Synchronisieren Ihrer Methoden erstellen müssen. Im Vergleich dazu können Sie eine extrinsische Sperre verwenden, indem Sie synchronized(myLock) {...} aufrufen.

Dies ist ein Auszug aus dem Buch Java concurrency in practice: „Die Tatsache, dass jedes Objekt eine eingebaute Sperre hat, ist nur eine Bequemlichkeit, so dass Sie nicht explizit Sperrobjekte erstellen müssen“

Das Buch sagt auch:

Es gibt keine inhärente Beziehung zwischen der intrinsischen Sperre eines Objekts und seinem Status; Die Felder eines Objekts müssen nicht durch seine eigene -Sperre geschützt werden, obwohl dies eine vollkommen gültige Sperrkonvention ist, die von vielen Klassen verwendet wird. Das Erlangen der Sperre, die mit einem Objekt verknüpft ist, verhindert nicht, dass andere Threads auf dieses Objekt zugreifen. Die einzige Sache, die das Erlangen einer Sperre verhindert, ist, dass ein anderer Thread die gleiche Sperre erwirbt . Die Tatsache, dass jedes Objekt über eine integrierte Sperre verfügt, ist nur ein Vorteil, sodass Sie keine Sperrobjekte explizit erstellen müssen. [9] Es liegt an Ihnen, Sperrprotokolle oder Synchronisierungsregeln zu erstellen, mit denen Sie sicher auf den freigegebenen Status zugreifen und sie einheitlich in Ihrem Programm verwenden können.

Aber in der Fußnote heißt es:

[9] Im Nachhinein diese Entscheidung Design war wahrscheinlich ein schlechter: nicht nur kann es verwirrend sein, aber es zwingt JVM Implementierer zu machen Kompromisse zwischen Objektgröße und Sperrleistung.

Und Ihre letzten Fragen zu beantworten: Sie werden nicht in der Lage sein, die synchronisierten Methoden von einem anderen Thread zu nennen, aber man kann aus dem gleichen Thread halte Eingabe (intrinsische Sperren werden einspringenden). Man muss sich also vorstellen, in diesem Fall als serialisierender Methodenzugriff von verschiedenen Aufrufer-Threads zu sperren.

Wenn Sie unsachgemäßes Sperren verwenden und dann Lebendigkeitsgefahren einführen, dann ist es ja vereitelt. Deshalb müssen Sie sicherstellen, dass Ihre konkurrierenden Threads nicht zu hart miteinander konkurrieren.

Als Brian Goetz puts in this blog entry:

In einer Anwendung Verwendung von Synchronisations-Tuning, dann sollten wir hart versuchen, die Menge der tatsächlichen Konflikte zu reduzieren, anstatt einfach nur versuchen bei allen

mit Synchronisation zu vermeiden
+1

Danke für deine Antwort. Ich denke, ich bin jetzt ein bisschen klarer darüber. – Swapnil

+0

@Swapnil Gern geschehen. Glückliche Kodierung! –

1

Ja, Sie können aufgrund der intrinsischen Sperre keine andere synchronisierte Methode für dasselbe Objekt aufrufen. Was auf Objektebene ist, wird nur 1 Thread erwerben.

1

Es spielt keine Rolle, ob die synchronized-Methode zu derselben Klasse gehört oder nicht, wichtig ist, ob der aufrufende Thread der Methode die Sperre erwirbt oder nicht, wenn dies der Fall ist, wird der kritische Abschnitt eingegeben weil das Schloss reentrant ist.

Wenn es nicht der Fall ist, dann ein rekursiver Aufruf zu einem Deadlock führen würde,

fn(){ 
synchronized(mutex){ // the current thread has already acquired the mutex 
    fn(); 
} 
} 

fn hier gewohnt Sackgasse, weil die Sperre einspringenden, das heißt (der Faden, der bereits kann die Sperre zu erwerben Geben Sie den kritischen Bereich erneut ein und verleihen Sie ihn erneut, solange er noch erworben wird.

+0

sry, aber ich habe meine Frage aktualisiert, um klarer zu sein. Meine Frage betrifft einen anderen Thread, der eine andere "synchronisierte" Methode aufruft. – Swapnil

2

Scheint, Sie haben ein Missverständnis (weiß nicht, wenn es die falsche Schlussfolgerung), dass niemand darauf hingewiesen hat. Wie auch immer, eine kurze Antwort:

Intrinsic Lock: Denken Sie einfach, als ob jedes Objekt in JVM intern eine Sperre hat. synchronized Schlüsselwörter versucht, die Sperre des Zielobjekts zu erwerben.Jedes Mal, wenn Sie synchronized (a) { doSomething; }, eigentlich das, was passiert ist,

  1. das Schloss in a ist
  2. Code innerhalb des synchronisierten Block erworben wird ausgeführt (doSomething)
  3. die Sperre in a

und ich wünsche Sie wissen

public synchronized void foo() { 
    doSomething; 
} 

ist vom Konzept her die gleichen wie

public void foo() { 
    synchronized(this) { 
     doSomething; 
    } 
} 

Ok, auf Ihre Frage zurückgehen, ist das größte Problem, imho ist:

Für mich bedeutet dies, dass, wenn ich rufe ein synchronisiertes Verfahren von einem der Fäden, werde ich halten, die intrinsischen Verriegelung der seit und Gewinden ...

Es ist falsch. Wenn Sie eine synchronisierte Methode aufrufen, sind Sie nicht erhalten Sie die Sperre der Thread.

Stattdessen dass Gewinde wird besitzen die intrinsische Sperre des Objekt, das die Methode „besitzen“.

z.B. In Thread1 haben Sie a.foo() aufgerufen und davon ausgegangen, dass foo() synchronisiert ist. thread1 wird die intrinsische Sperre des Objektes a beziehen.

In ähnlicher Weise, wenn AClass.bar() aufgerufen wird (und bar ist synchronisiert und eine statische Methode), wird die intrinsische Sperre von AClass Klassenobjekt erworben werden.

+0

Also, wenn ich eine synchronisierte Methode von einem ** Thread ** aufrufen und die intrinsische Sperre des ** Objekts ** erhalten, kann ich dann eine andere synchronisierte Methode von einem anderen Thread aufrufen? Sorry für eine frühere Doppeldeutigkeit in meiner Frage. – Swapnil

+0

ein anderer Thread, der versucht, auf THAT-Objekt zu synchronisieren (explizit synchronisiert, Aufruf einer Synchronisationsmethode für dieses Objekt usw.) muss warten. Sie müssen sich klar darüber sein, * was * synchronisierte Methode es ist. Wenn es nur eine synchronisierte Methode eines anderen nicht verwandten Objekts ist, ist es natürlich in Ordnung –

1

kann ich nicht eine andere synchronisierte Methode der gleichen Klasse aufrufen? Wenn ja, dann ist der ganze Zweck der synchronisierten Methoden besiegt. Ist es nicht?

Nein, Sie können nicht andere synchronized Methode auf demselben Objekt für Objekt-Ebene Sperre aufrufen und Sie können nicht andere static sysnchronized Methode auf derselben Klasse aufrufen.

Aber es besiegt den Zweck der Synchronisierung nicht.

Wenn Sie die anderen Dokumentationsseite synchronized Methoden folgen:

diese Methoden machen synchronized zwei Effekte hat:

  1. Erstens ist es nicht möglich, dass zwei Anrufungen von synchronisierten Methoden auf dem gleichen Objekt zu verschachteln.Wenn ein Thread eine synchronisierte Methode für ein Objekt ausführt, werden alle anderen Threads aufgerufen, die synchronisierte Methoden für denselben Objektblock aufrufen (Ausführung aussetzen), bis der erste Thread mit dem Objekt ausgeführt wird.
  2. Zweitens, wenn eine synchronisierte Methode beendet wird, stellt sie automatisch eine Vor-Vor-Beziehung mit jedem nachfolgenden Aufruf einer synchronisierten Methode für dasselbe Objekt her. Dies garantiert, dass Änderungen am Status des Objekts für alle Threads sichtbar sind.

Wenn Sie erlauben, zwei synchronized Verfahren parallel laufen zu lassen. Sie müssen Speicherinkonsistenzfehler bei freigegebenen Daten erhalten.

Auf eine andere Anmerkung, Lock bietet bessere Alternative synchronized Konstrukt.

Related SE Frage:

Synchronization vs Lock

+0

Vielen Dank für die Antwort und die Referenzen. Obwohl Ihre Antwort gut genug ist, hat die von @ Captain Fogetti detailliertere Erklärungen mit Links zu anderen nützlichen Ressourcen. Also, ich markiere das als richtig. Danke noch einmal. – Swapnil

2

Eine Sperre kann zu einem Zeitpunkt nur von einem Faden gehalten werden. Das besiegt den Zweck nicht; dass ist der Zweck.

Threads mut ually ex clude sie von gleichzeitiger Wirkung in kritischen Abschnitten durch eine Sperre zu erwerben, oder Mutex. Dies bietet eine effektive Atomarität um eine Reihe unterschiedlicher Aktionen herum, so dass andere Threads niemals Zwischenzustände sehen, die Konsistenzgarantien verletzen könnten.

0

Verriegelungen können in zwei Klassen unterteilt werden - "Wiedereintrittssperre" und "nicht Wiedereintrittssperre". In Java 'synchronisiert', Basisimplementierung der Schnittstelle Sperre (Klasse ReentrantLock), Schnittstelle ReadWriteLock (Klasse ReentrantReadWriteLock) - sind reentrant. Reentrancy bedeutet - ein Thread kann immer wieder das Schloss halten.

Verwandte Themen