List<String> list = Collections.synchronizedList(new ArrayList<String>());
synchronized (list) {
list.add("message");
}
Wird der Block "synchronisiert (Liste) {}" hier wirklich benötigt?
java
collections
synchronization
Romsky
quelle
quelle
Es kommt auf den genauen Inhalt des
synchronized
Blocks an:Wenn der Block eine einzelne atomare Operation für die Liste ausführt (wie in Ihrem Beispiel),
synchronized
ist die überflüssig.Wenn der Block führt auf der Liste mehrere Operationen - und Bedürfnisse die Sperre für die Dauer der Verbindung Betrieb aufrecht zu erhalten - dann das
synchronized
ist nicht überflüssig. Ein häufiges Beispiel hierfür ist das Durchlaufen der Liste.quelle
Der zugrunde liegende Code für die Additionsmethode Collections.synchronizedList lautet:
public void add(int index, E element) { synchronized (mutex) {list.add(index, element);} }
In Ihrem Beispiel ist es also nicht erforderlich, eine Synchronisierung hinzuzufügen.
quelle
Es ist auch wichtig zu beachten, dass alle Methoden, die Iteratoren verwenden, z. B. Collections.sort (), ebenfalls in einem synchronisierten Block gekapselt werden müssen.
quelle
Lesen Sie dieses Oracle-Dokument
Es heißt "Es ist unbedingt erforderlich, dass der Benutzer die zurückgegebene Liste manuell synchronisiert, wenn er darüber iteriert."
quelle
Wie von anderen erwähnt, sind die synchronisierten Sammlungen threadsicher , aber die zusammengesetzten Aktionen für diese Sammlungen sind standardmäßig nicht garantiert threadsicher.
Laut JCIP können die üblichen zusammengesetzten Aktionen sein
Der synchronisierte Codeblock des OP ist keine zusammengesetzte Aktion, also kein Unterschied, ob er hinzugefügt wird oder nicht.
Nehmen wir das Beispiel von JCIP und ändern Sie es ein wenig, um zu verdeutlichen, warum es notwendig ist, die zusammengesetzten Aktionen mit Sperre zu schützen.
Es gibt zwei Methoden, die mit derselben Sammlung arbeiten
list
, die von umbrochen wurdeCollections.synchronizedList
public Object getLast(List<String> list){ int lastIndex = list.size() - 1; return list.get(lastIndex); } public void deleteLast(List<String> list){ int lastIndex = list.size() - 1; list.remove(lastIndex); }
Wenn Methoden
getLast
unddeleteLast
gleichzeitig von zwei verschiedenen Threads aufgerufen werden, können die folgenden Zwischenblätter auftreten undgetLast
werden ausgelöstArrayIndexOutOfBoundsException
. Angenommen, der StromlastIndex
beträgt 10.Thread A (deleteLast) ->
Thread B (getLast) entfernen --------------------> get
Der Faden A.
remove
das Element vor demget
Betrieb in Thread B. Somit noch der Thread B 10 , wie die VerwendunglastIndex
zu nennenlist.get
Verfahren, wird es gleichzeitig Problem führen.quelle