In der JSON-Java-Bibliothek ( org.json.JSONArray ) habe ich habe dieses Code-Snippet mit einem synchronized
-Block um eine methodenlokale Variable gefunden
Ich verstehe die Notwendigkeit für die Synchronisation hier nicht, da StringWriter
nur lokal für die gegebene Methode ist (und warum die Synchronisation auf dem Buffer ist). Ist die Synchronisation hier wirklich nötig, und wenn, warum?
Dies kann eine Leistungsoptimierung sein. Im Orakel jvm ist das Wiedererlangen eines bereits gehaltenen Schlosses sehr schnell. Vermutlich führt der Aufruf write
zahlreiche Aufrufe in den StringBuffer aus. Durch Sperren vor dem Aufruf von write
wird die Sperre durch alle diese Anrufe gehalten, anstatt für jeden Anruf freigegeben und erneut abgerufen zu werden.
Der leere Konstruktor für StringWriter
ist
Nichts wird geteilt, daher ist der synchronized
-Block unnötig.
Es sei denn ... write
delegiert an einen anderen Thread, aber ich bezweifle das ernsthaft.
getBuffer()
gibt eine StringBuffer
zurück, und gemäß der Dokumentation ist ein StringBuffer
bereits synchronisiert:
String-Puffer sind sicher für die Verwendung durch mehrere Threads. Die Methoden werden bei Bedarf synchronisiert, so dass sich alle Vorgänge in einer bestimmten Instanz so verhalten, als ob sie in einer seriellen Reihenfolge auftreten, die der Reihenfolge der Methodenaufrufe der einzelnen beteiligten Threads entspricht.
Das bedeutet, dass das erneute Synchronisieren auf StringBuffer
total übertrieben ist. Änderungen an StringWriter
werden automatisch synchronisiert, da sie das synchronisierte StringBuffer
intern verwenden.
Da die Instanz StringWriter
lokal für den Methodenaufruf ist, ist es unmöglich, mehrere Threads gleichzeitig auf dieselbe Instanz zugreifen zu lassen, was ebenfalls eine Synchronisierung unnötig macht.
Es ist ein Fehler. Jeder Thread erzeugt seine eigene lokale Variable in der Methode und synchronisiert sich darauf. Jedes Mal, wenn die Methoden-Threads eingegeben werden, erstellen sie ihren eigenen Objekt-Monitor, der nicht von einem anderen Thread gehalten werden kann, weil er lokal ist und nur auf dem Stack des Threads lebt!
Tags und Links java synchronized