Kann jemand bitte den Unterschied zwischen diesen beiden Beispielen im Zusammenhang mit der Objektverriegelung erklären:
%Vor%Und
%Vor% Ich weiß, dass das erste Beispiel eine Sperre für die this
-Instanz und die zweite eine Sperre für die aStringBufferObject-Instanz erhält. Aber ich verstehe nicht wirklich, was die Wirkung oder der Unterschied der beiden ist.
Zum Beispiel können im zweiten Beispiel Threads weiterhin den Code innerhalb des synchronisierten Blocks ausführen, weil die Sperre nicht mit der 'this' Instanz zusammenhängt?
Ich weiß, dass das Synchronisieren einer Methode oder eines Codeblocks verhindert, dass mehrere Threads gleichzeitig auf diesen Block / diese Methode zugreifen, aber wozu dient die Angabe des Objekts, für das es gesperrt werden soll, und was ist der Unterschied in der Art des Objekts? wie in den obigen Beispielen angegeben?
Was ist der Zweck der Angabe des zu sperrenden Objekts?
Oft ist es einfacher, auf this
oder auf der Instanz Class
zu synchronisieren (für statische Methoden). Aber es gibt Fälle, in denen Sie für ein bestimmtes Objekt anstelle der impliziten Sperre ( this
) synchronisieren müssen. Solche Fälle umfassen:
this
zu verwenden. Sie können nur auf Object
s synchronisieren, da jedes Object
einem impliziten Monitor in Java zugeordnet ist. Primitive verfügen nicht über solche impliziten Monitore. Daher müssen Sie ein Sperrobjekt verwenden. Die Verwendung der Wrapper-Klassen ist eine schlechte und falsche Wahl, besonders wenn Sie das Sperrobjekt im geschützten Block ändern . this
keine Garantie für die Threadsicherheit bietet. Wenn Sie beispielsweise den Zugriff auf eine ArrayList
-Instanz synchronisieren, die über Instanzen der Klasse A
gemeinsam genutzt wird, ist die Synchronisierung für eine Instanz von A
nutzlos. Ein Thread erstellt möglicherweise eine neue Instanz von A
und erhält Zugriff auf die Liste, während ein anderer Thread sie ändert. Wenn Sie eine andere Sperre verwenden, für die alle Threads konkurrieren müssen, können Sie die Liste schützen. Diese Sperre könnte die sein, die mit A.class
verknüpft ist, aber es könnte jedes Objekt sein, das dieselben Garantien bietet. Im Folgenden finden Sie ein Beispiel für die Verwendung von Split-Sperren:
%Vor% Sie würden geteilte Sperren verwenden, wenn Sie sicherstellen können, dass die gleichzeitige Ausführung von method1
und method2
nicht gegen die Klasseninvarianten verstößt. Auf diese Weise können Sie die Leistung in Threads verbessern, die Zugriff auf dasselbe Objekt benötigen, aber unterschiedliche Methoden aufrufen.
Bei Ihrer anderen Frage,
Zum Beispiel können im zweiten Beispiel Threads weiterhin den Code innerhalb des synchronisierten Blocks ausführen, weil die Sperre nicht mit der 'this' Instanz zusammenhängt?
Im zweiten Beispiel muss jeder Thread, der die geschützte Region betritt, die mit aStringBufferObject
verknüpfte Sperre erhalten. Wenn ein anderer Thread diese Sperre hält, wird der aktuelle Thread nicht weiter fortfahren. Wenn Sie this
angeben, muss der Thread die mit dem aktuellen Objekt verknüpfte Sperre abrufen. In beiden Fällen muss ein Thread eine Sperre erhalten; Die Beispiele unterscheiden sich nur in dem Objekt, das als Sperre verwendet wird.
Synchronisieren für ein Objekt bedeutet, dass andere Blöcke, die sich auf demselben Objekt synchronisieren, warten müssen. Zum Beispiel:
%Vor% Wenn Sie methodA()
in einem Thread aufrufen und dann methodB()
in einem anderen Thread aufrufen, wird methodB()
nicht beendet, bevor methodA()
beendet ist.
Der synchronized
-Block ist ein Monitor, der keine Details zum Sperren und Entsperren eines Mutex enthält. Da jedes Objekt in Java über eine interne Sperre verfügt (siehe Quellcode der Object
-Klasse), wird die JVM bei Verwendung der synchronized
-Anweisung Ihnen helfen, den kritischen Abschnitt zu synchronisieren. Sie können den Block auch selbst synchronisieren. Verwenden Sie ReentrantLock im Paket java.util.concurrent.locks
.
Tags und Links java multithreading scjp