Cosa sono gli iteratori fail-safe e fail-fast in Java


101

Esistono due tipi di iteratori in Java: fail-safe e fail-fast.

Cosa significa, ed è la differenza tra loro?


3
miglior link che ho trovato javahungry.blogspot.com/2014/04/…
Premraj

2
Si noti che le specifiche Java SE non utilizzano il termine "fail-safe" per descrivere alcun iteratore. Raccomando quindi di evitare questo termine. Vedi anche stackoverflow.com/a/38341921/1441122
Stuart Marks

Risposte:


84

Qual'è la differenza tra loro ...

"Fail-safe" ( in ingegneria ) significa che qualcosa si guasta in un modo che non causa danni minimi o nulli. A rigor di termini, non esiste in Java un iteratore a prova di errore. Se un iteratore fallisce (nel senso normale di "fail"), ci si può aspettare che si verifichi un danno.

Sospetto che in realtà intendi iteratori "debolmente coerenti". Il javadoc dice:

"La maggior parte delle implementazioni di Collection simultanee (inclusa la maggior parte delle code) differiscono anche dalle consuete convenzioni java.util in quanto i loro iteratori e spliteratori forniscono un attraversamento debolmente coerente piuttosto che un rapido errore."

Tipicamente, consistenza debole significa che se una raccolta viene modificata contemporaneamente a un'iterazione, le garanzie di ciò che vede l'iterazione sono più deboli. (I dettagli verranno specificati in ogni javadocs delle classi di raccolta simultanee.)

"Fail-fast" ( nella progettazione dei sistemi ) significa che la condizione di guasto viene controllata in modo aggressivo in modo che la condizione di guasto venga rilevata (dove possibile 1 ) prima che si possa causare un danno eccessivo. In Java, un iteratore fail-fast fallisce lanciando un file ConcurrentModificationException.

L'alternativa a "fail-fast" e "debolmente coerente" è semantica in cui l'iterazione fallisce in modo imprevedibile; ad esempio, a volte dare la risposta sbagliata o lanciare un'eccezione inaspettata. (Questo era il comportamento di alcune implementazioni standard Enumerationdell'API nelle prime versioni di Java.)

... e sono diversi dall'iteratore che usiamo per la raccolta.

No. Queste sono proprietà degli iteratori implementati dai tipi Collection standard; cioè sono "fail fast" o "debolmente consistenti" ... se usati correttamente rispetto alla sincronizzazione e al modello di memoria Java 1 .


Gli iteratori fail-fast vengono in genere implementati utilizzando un volatilecontatore sull'oggetto di raccolta.

  • Quando la raccolta viene aggiornata, il contatore viene incrementato.
  • Quando Iteratorviene creato un, il valore corrente del contatore viene incorporato Iteratornell'oggetto.
  • Quando Iteratorviene eseguita un'operazione, il metodo confronta i due valori del contatore e lancia un CME se sono diversi.

Al contrario, gli iteratori debolmente coerenti sono in genere leggeri e sfruttano le proprietà delle strutture di dati interne di ciascuna raccolta simultanea. Non esiste uno schema generale. Se sei interessato, leggi il codice sorgente per diverse classi di raccolta.


1 - Il pilota è che il comportamento veloce presuppone che l'applicazione id correttamente rispetto alla sincronizzazione e al modello di memoria. Ciò significa che (ad esempio) se si esegue un'iterazione ArrayListsenza una corretta sincronizzazione, il risultato potrebbe essere un risultato di elenco danneggiato. Il meccanismo "fast fail" rileverà probabilmente la modifica simultanea (sebbene ciò non sia garantito), ma non rileverà il danneggiamento sottostante. Ad esempio, javadoc per Vector.iterator()dice questo:

"Il comportamento fail-fast di un iteratore non può essere garantito poiché è, in generale, impossibile fornire garanzie concrete in presenza di modifiche simultanee non sincronizzate. Gli iteratori fail-fast eseguono ConcurrentModificationExceptionil massimo sforzo. Pertanto, sarebbe sbagliato scrivere un programma che dipendeva da questa eccezione per la sua correttezza: il comportamento veloce degli iteratori dovrebbe essere usato solo per rilevare i bug. "


Forse un po 'irrilevante ma potrebbe anche essere complementare per questa domanda. E lo stile dell'istantanea utilizzato, ad esempio, da CoW? Più specificamente, non capisco come l'array sottostante (o l'istantanea) su cui l'iteratore CoW itera "mai" vede le modifiche apportate da altri thread poiché siamo ancora in grado di richiamare setArrayqualsiasi modifica.
stdout

Ho deciso che parlare dell'implementazione di iteratori debolmente coerenti va oltre lo scopo di questa domanda e risposta.
Stephen C

42

Sono tipi piuttosto veloci e debolmente coerenti :

Iteratori dal java.utillancio del pacchetto ConcurrentModificationExceptionse la raccolta è stata modificata dai metodi della raccolta (aggiungi / rimuovi) durante l'iterazione

Gli iteratori del java.util.concurrentpacchetto in genere eseguono l'iterazione su un'istantanea e consentono modifiche simultanee ma potrebbero non riflettere gli aggiornamenti della raccolta dopo la creazione dell'iteratore.


Iterator è un esempio di fail-fast mentre l'enumerazione è a prova di errore
Ajay Sharma

5
@AjaySharma - Errato su due punti. 1) Né Iteratoro Enumerationspecificare il comportamento come fail-fast o fail-safe. Sono implementazioni specifiche (cioè i metodi di raccolta iterator()/ elements()etc specifici che restituiscono questi oggetti) che specificano il comportamento. 2) Le implementazioni tipiche dell'enumerazione non sono né a prova di errore né a prova di errore .
Stephen C

22

L'unica differenza è che l'iteratore fail-safe non genera alcuna eccezione, contrariamente all'iteratore fail-fast.

Se Collection viene modificato strutturalmente mentre un thread sta iterando su di esso. Questo perché funzionano sul clone di Collection anziché sulla raccolta originale ed è per questo che sono chiamati iteratori fail-safe.

L'iteratore di CopyOnWriteArrayList è un esempio di Iteratore fail-safe anche l'iteratore scritto da ConcurrentHashMap keySet è anche un iteratore fail-safe e non lancia mai ConcurrentModificationException in Java.


Non vedo che l'iteratore ConcurrentHashMap funzioni su clone () .. :( Alcune volte rifletterà alcuni aggiornamenti durante l'iterazione ..
Kanagavelu Sugumar

0

Questo scenario si riferisce alla "elaborazione simultanea", significa che più di un utente accede alla stessa risorsa. In tale situazione, uno degli utenti tenta di modificare quella risorsa che causa la "ConcurrentProcessingException" perché in quel caso l'altro utente ottiene dati non corretti. Entrambi questo tipo si riferiscono a questo tipo di situazione.

In termini semplici,

Fail-Fast:

  • Gli iteratori lanciano immediatamente ConcurrentModificationException se si verificano modifiche strutturali (aggiunta, aggiornamento, eliminazione).
  • Esempio: ArrayList, HashMap, TreeSet

A prova di errore:

  • Qui gli iteratori non lanciano eccezioni perché operano sul clone della raccolta, non su quello originale. Quindi, sono iteratori a prova di errore.
  • Esempio: CopyOnWriteArrayList, ConcurrentHashMap
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.