Andere Antworten haben das Problem erkannt:
-
Die Iteratoren für synchronisierte Sammlungen sind nicht synchronisiert. Sie sind einfach die Iteratoren, die von den Sammlungsobjekten innerhalb der Wrapper-Klassen zurückgegeben werden.
-
Viele Sammlungsklassen (einschließlich ArrayList
) verwenden einen ausfallsicheren Mechanismus, um gleichzeitige Änderungen während der Iteration zu erkennen. Dieses Verhalten ist in den Javadocs für die jeweiligen Klassen eindeutig dokumentiert. Dies ist, was Sie sehen.
Dies ist nicht bei allen Sammelklassen der Fall. Zum Beispiel, viele der java.util.Concurrent...
Sammlungsklassen erlauben gleichzeitige Änderungen während der Iteration, lockern aber die Semantik der Iterationsfolge, so dass die Ergebnisse der Änderungen kann, muss aber nicht in den vom Iterator zurückgegebenen Objekten ersichtlich sein.
Die Javadoc für die Collections.synchronizedList()
erklärt, wie man den Iterator synchronisiert. Im Grunde tun Sie dies:
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
(Nebenbei bemerkt: Normalerweise ist es nicht sicher anzunehmen, dass so etwas funktioniert. Theoretisch könnte die synchronisierte Liste ein privates Sperrobjekt verwenden, und die synchronized
Anweisung würde gleichzeitige Änderungen nicht ausschließen. Die Javadocs sagen jedoch, dass dies in diesem Fall zu tun ist ... es ist also sicher).
Das Problem dabei ist, dass durch das Sperren der Sammlung ein potenzieller Engpass für die Gleichzeitigkeit entsteht. Die Alternative dazu ist die Verwendung einer Copy-on-Write-Datenstruktur, die intern eine Kopie der relevanten Teile der Sammlung erstellt. Dieser Ansatz bedeutet, dass ein Iterator eine Momentaufnahme der Sammlung sieht. Änderungen an der Sammlung können während einer Iteration vorgenommen werden, aber der Iterator sieht sie nicht. Das Problem bei Copy-on-Write ist, dass Änderungen potenziell sehr viel teurer sind.
Letztendlich müssen Sie die Merkmale und Kosten der verschiedenen Erfassungsarten im Hinblick auf die gleichzeitige Änderung gegenüber Ihren tatsächlichen Anforderungen abwägen. Können Sie sich damit abfinden, dass der Iterator nicht alle gleichzeitigen Änderungen sieht?