Was sind ausfallsichere und ausfallsichere Iteratoren in Java?

101

In Java gibt es zwei Arten von Iteratoren: ausfallsicher und ausfallsicher.

Was bedeutet das und ist der Unterschied zwischen ihnen?

Prateek
quelle
3
bester Link, den ich gefunden habe javahungry.blogspot.com/2014/04/…
Premraj
2
Beachten Sie, dass in den Java SE-Spezifikationen der Begriff "ausfallsicher" nicht zur Beschreibung von Iteratoren verwendet wird. Ich empfehle daher, diesen Begriff zu vermeiden. Siehe auch stackoverflow.com/a/38341921/1441122
Stuart Marks

Antworten:

84

Was ist der Unterschied zwischen ihnen ...

"Ausfallsicher" ( in der Technik ) bedeutet, dass etwas auf eine Weise ausfällt, die keinen oder nur minimalen Schaden verursacht. Genau genommen gibt es nicht so etwas in Java als ausfallsichere Iterator. Wenn ein Iterator ausfällt (im normalen Sinne von "fehlgeschlagen"), können Sie mit Schäden rechnen.

Ich vermute, dass Sie tatsächlich "schwach konsistente" Iteratoren meinen. Der Javadoc sagt:

"Die meisten gleichzeitigen Collection-Implementierungen (einschließlich der meisten Queues) unterscheiden sich auch von den üblichen java.util-Konventionen darin, dass ihre Iteratoren und Spliteratoren eher eine schwach konsistente als eine schnelle Fail-Traversal-Funktion bieten."

In der Regel bedeutet schwache Konsistenz, dass die Garantien für das, was die Iteration sieht, schwächer sind, wenn eine Sammlung gleichzeitig mit einer Iteration geändert wird. (Die Details werden in den Javadocs der einzelnen gleichzeitigen Sammlungsklassen angegeben.)

"Fail-Fast" ( im Systemdesign ) bedeutet, dass der Fehlerzustand aggressiv überprüft wird, damit der Fehlerzustand (soweit möglich 1 ) erkannt wird, bevor zu viel Schaden angerichtet werden kann. In Java schlägt ein ausfallsicherer Iterator fehl, indem er a auslöstConcurrentModificationException .

Die Alternative zu "ausfallsicher" und "schwach konsistent" ist semantisch, wenn die Iteration unvorhersehbar fehlschlägt. zB um manchmal die falsche Antwort zu geben oder eine unerwartete Ausnahme auszulösen. (Dies war das Verhalten einiger Standardimplementierungen der EnumerationAPI in früheren Versionen von Java.)

... und unterscheiden sie sich von dem Iterator, den wir für die Sammlung verwenden.

Nein. Dies sind Eigenschaften der Iteratoren, die von Standard-Sammlungstypen implementiert werden. dh sie sind entweder "schnell ausfallen" oder "schwach konsistent" ... wenn sie in Bezug auf die Synchronisation und das Java-Speichermodell 1 korrekt verwendet werden .


Fail-Fast-Iteratoren werden normalerweise mithilfe eines volatileZählers für das Erfassungsobjekt implementiert .

  • Wenn die Sammlung aktualisiert wird, wird der Zähler erhöht.
  • Wenn ein Iteratorerstellt wird, wird der aktuelle Wert des Zählers in das IteratorObjekt eingebettet .
  • Wenn eine IteratorOperation ausgeführt wird, vergleicht die Methode die beiden Zählerwerte und löst eine CME aus, wenn sie unterschiedlich sind.

Im Gegensatz dazu sind schwach konsistente Iteratoren in der Regel leichtgewichtig und nutzen die Eigenschaften der internen Datenstrukturen jeder gleichzeitigen Sammlung. Es gibt kein allgemeines Muster. Wenn Sie interessiert sind, lesen Sie den Quellcode für verschiedene Sammlungsklassen.


1 - Der Fahrer ist der Ansicht, dass bei einem ausfallsicheren Verhalten davon ausgegangen wird, dass die Anwendungs-ID in Bezug auf die Synchronisation und das Speichermodell korrekt ist. Das bedeutet, dass (zum Beispiel) wenn Sie eine ArrayListohne ordnungsgemäße Synchronisation iterieren , das Ergebnis ein beschädigtes Listenergebnis sein kann. Der "Fast Fail" -Mechanismus erkennt wahrscheinlich die gleichzeitige Änderung (obwohl dies nicht garantiert ist), erkennt jedoch nicht die zugrunde liegende Beschädigung. Als Beispiel sagt javadoc für FolgendesVector.iterator() :

"Das ausfallsichere Verhalten eines Iterators kann nicht garantiert werden, da es im Allgemeinen unmöglich ist, bei nicht synchronisierten gleichzeitigen Änderungen harte Garantien zu geben. Ausfallsichere Iteratoren werfen ConcurrentModificationExceptionauf Best-Effort-Basis. Daher wäre dies der Fall." Es ist falsch, ein Programm zu schreiben, dessen Richtigkeit von dieser Ausnahme abhängt: Das ausfallsichere Verhalten von Iteratoren sollte nur zum Erkennen von Fehlern verwendet werden. "

Stephen C.
quelle
Vielleicht ein bisschen irrelevant, aber auch komplementär zu dieser Frage. Was ist mit dem Snapshot-Stil, der beispielsweise von der CoW verwendet wird? Insbesondere verstehe ich nicht ganz, wie das zugrunde liegende Array (oder der Snapshot), über das der CoW-Iterator iteriert, "nie" Änderungen sieht, die von anderen Threads vorgenommen werden, da wir immer setArraynoch Änderungen aufrufen können.
Stdout
Ich entschied, dass das Sprechen über die Implementierung schwach konsistenter Iteratoren den Rahmen dieser Fragen und Antworten sprengt.
Stephen C
42

Sie sind eher ausfallsichere und schwach konsistente Typen:

Iteratoren aus java.utilPaketwurfConcurrentModificationException wenn die Sammlung während der Iteration durch die Methoden der Sammlung (Hinzufügen / Entfernen) geändert wurde

Iteratoren aus dem java.util.concurrentPaket iterieren normalerweise über einen Snapshot und ermöglichen gleichzeitige Änderungen, spiegeln jedoch möglicherweise keine Sammlungsaktualisierungen wider, nachdem der Iterator erstellt wurde.

Evgeniy Dorofeev
quelle
Iterator ist ein Beispiel für Fail-Fast, während die Aufzählung Fail-Safe ist
Ajay Sharma
5
@ AjaySharma - In zweierlei Hinsicht falsch. 1) Weder noch Iteratoroder Enumerationgeben Sie das Verhalten als ausfallsicher oder ausfallsicher an. Es sind bestimmte Implementierungen (dh die spezifischen Collection iterator()/ elements()etc-Methoden, die diese Objekte zurückgeben), die das Verhalten angeben. 2) Typische Enumeration-Implementierungen sind weder ausfallsicher noch ausfallsicher .
Stephen C
22

Der einzige Unterschied besteht darin, dass der ausfallsichere Iterator im Gegensatz zum ausfallsicheren Iterator keine Ausnahme auslöst.

Wenn Collection strukturell geändert wird, während ein Thread darüber iteriert. Dies liegt daran, dass sie mit dem Klon der Sammlung anstelle der ursprünglichen Sammlung arbeiten und deshalb als ausfallsicherer Iterator bezeichnet werden.

Der Iterator von CopyOnWriteArrayList ist ein Beispiel für einen ausfallsicheren Iterator. Der von ConcurrentHashMap geschriebene Iterator keySet ist auch ein ausfallsicherer Iterator und löst niemals ConcurrentModificationException in Java aus.

Juned Ahsan
quelle
Ich sehe nicht, dass der ConcurrentHashMap-Iterator an clone () arbeitet .. :(
Manchmal
0

Dieses Szenario bezieht sich auf "gleichzeitige Verarbeitung". Dies bedeutet, dass mehr als ein Benutzer auf dieselbe Ressource zugreift. In einer solchen Situation versucht einer der Benutzer, diese Ressource zu ändern, die die 'ConcurrentProcessingException' verursacht, da in diesem Fall andere Benutzer falsche Daten erhalten. Beide dieser Art beziehen sich auf diese Art von Situation.

In einfachen Worten,

Fail-Fast:

  • Iteratoren lösen sofort die ConcurrentModificationException aus, wenn strukturelle Änderungen (Hinzufügen, Aktualisieren, Löschen) auftreten.
  • Beispiel: ArrayList, HashMap, TreeSet

Ausfallsicher :

  • Hier werfen Iteratoren keine Ausnahme, da sie auf dem Klon der Sammlung arbeiten, nicht auf dem Original. Damit sie ausfallsichere Iteratoren sind.
  • Beispiel: CopyOnWriteArrayList, ConcurrentHashMap
Dhwanil Patel
quelle