Wann immer auf SO eine Frage zur Java-Synchronisierung auftaucht, sind einige Leute sehr eifrig dabei, darauf hinzuweisen, dass synchronized(this)
sollte vermieden werden. Stattdessen sei eine Sperre für eine private Referenz vorzuziehen.
Einige der genannten Gründe sind:
- einige böser Code kann Ihr Schloss stehlen (sehr beliebt, es gibt auch eine "zufällige" Variante)
- alle synchronisierten Methoden innerhalb derselben Klasse verwenden genau dieselbe Sperre, was den Durchsatz verringert
- Sie geben (unnötigerweise) zu viele Informationen preis.
Andere Leute, darunter auch ich, argumentieren, dass synchronized(this)
ist ein Idiom, das häufig verwendet wird (auch in Java-Bibliotheken), sicher ist und gut verstanden wird. Es sollte nicht vermieden werden, weil Sie einen Fehler haben und keine Ahnung haben, was in Ihrem Multithreading-Programm vor sich geht. Mit anderen Worten: Wenn es anwendbar ist, dann verwenden Sie es.
Ich bin daran interessiert, einige Beispiele aus der Praxis zu sehen (kein Foobar-Zeug), bei denen die Vermeidung einer Sperre auf this
ist vorzuziehen, wenn synchronized(this)
würde die Aufgabe ebenfalls erfüllen.
Deshalb: sollten Sie immer vermeiden synchronized(this)
und sie durch eine Sperre für eine private Referenz ersetzen?
Einige weitere Informationen (aktualisiert, sobald Antworten gegeben werden):
- es geht um die Synchronisierung von Instanzen
- sowohl implizit (
synchronized
Methoden) und explizite Form dersynchronized(this)
werden als - wenn Sie Bloch oder andere Autoritäten zu diesem Thema zitieren, lassen Sie nicht die Teile weg, die Ihnen nicht gefallen (z.B. Effektives Java, Artikel über Thread-Sicherheit: Normalerweise ist es die Sperre der Instanz selbst, aber es gibt Ausnahmen).
- wenn Sie eine andere Granularität für Ihre Sperren benötigen als
synchronized(this)
bietet, dannsynchronized(this)
ist nicht anwendbar, also ist das nicht das Problem
4 Stimmen
Ich möchte auch darauf hinweisen, dass der Kontext wichtig ist - der Teil "Typischerweise ist es die Sperre der Instanz selbst" steht in einem Abschnitt über die Dokumentation einer bedingt thread-sicheren Klasse, wenn Sie die Sperre öffentlich machen. Mit anderen Worten, dieser Satz gilt, wenn Sie diese Entscheidung bereits getroffen haben.
0 Stimmen
In Ermangelung einer internen Synchronisierung und wenn eine externe Synchronisierung erforderlich ist, ist die Sperre oft die Instanz selbst, so Bloch. Warum sollte dies also nicht auch bei interner Synchronisation mit Sperre auf "this" der Fall sein? (Die Bedeutung der Dokumentation ist ein anderes Thema.)
0 Stimmen
Es besteht ein Kompromiss zwischen erweiterter Granularität und zusätzlichem CPU-Cache- und Busanforderungs-Overhead, da das Sperren eines externen Objekts höchstwahrscheinlich eine separate Cache-Zeile erfordert, die geändert und zwischen CPU-Caches ausgetauscht werden muss (vgl. MESIF und MOESI).
3 Stimmen
Ich denke, in der Welt der defensiven Programmierung verhindert man Fehler nicht durch Idiome, sondern durch Code. Wenn mir jemand die Frage stellt: "Wie optimiert ist Ihre Synchronisierung?", möchte ich "Sehr" statt "Sehr, es sei denn, jemand anderes hält sich nicht an das Idiom" sagen.