Que sont les itérateurs à sécurité intégrée et rapide en Java

101

Il existe deux types d'itérateurs en Java: à sécurité intégrée et à sécurité intégrée.

Qu'est-ce que cela signifie et est la différence entre eux?

Prateek
la source
3
meilleur lien que j'ai trouvé javahungry.blogspot.com/2014/04/…
Premraj
2
Notez que les spécifications Java SE n'utilisent pas le terme «sécurité intégrée» pour décrire les itérateurs. Je recommande donc d'éviter ce terme. Voir aussi stackoverflow.com/a/38341921/1441122
Stuart marque le

Réponses:

84

Quelle est la différence entre eux ...

«Fail-safe» ( en ingénierie ) signifie que quelque chose échoue d'une manière qui ne cause aucun dommage ou un dommage minimal. À proprement parler, il n'existe pas en Java d'itérateur à sécurité intégrée. Si un itérateur échoue (dans le sens normal de «échec»), vous pouvez vous attendre à ce que des dommages se produisent.

Je soupçonne que vous entendez en fait des itérateurs "faiblement cohérents". Le javadoc dit:

"La plupart des implémentations de collection simultanées (y compris la plupart des files d'attente) diffèrent également des conventions java.util habituelles en ce que leurs itérateurs et séparateurs fournissent une traversée faiblement cohérente plutôt que rapide."

En règle générale, une cohérence faible signifie que si une collection est modifiée en même temps qu'une itération, les garanties de ce que voit l'itération sont plus faibles. (Les détails seront spécifiés dans chaque javadocs de classes de collection simultanées.)

«Fail-fast» ( dans la conception des systèmes ) signifie que la condition de défaillance est vérifiée de manière agressive afin que la condition de défaillance soit (si possible 1 ) détectée avant que trop de dommages ne puissent être causés. En Java, un itérateur rapide échoue en lançant un fichier ConcurrentModificationException.

L'alternative à "fail-fast" et "faiblement cohérent" est sémantique là où l'itération échoue de manière imprévisible; par exemple pour donner parfois la mauvaise réponse ou lancer une exception inattendue. (C'était le comportement de certaines implémentations standard de l' EnumerationAPI dans les premières versions de Java.)

... et sont-ils différents de l'itérateur que nous utilisons pour la collecte.

Non. Ce sont les propriétés des itérateurs implémentés par les types Collection standard; c'est-à-dire qu'ils sont soit "échouent rapidement" soit "faiblement cohérents" ... lorsqu'ils sont utilisés correctement par rapport à la synchronisation et au modèle de mémoire Java 1 .


Les itérateurs à échec rapide sont généralement implémentés à l'aide d'un volatilecompteur sur l'objet de collection.

  • Lorsque la collection est mise à jour, le compteur est incrémenté.
  • Lors de la création d'un Iterator, la valeur actuelle du compteur est incorporée dans l' Iteratorobjet.
  • Lorsqu'une Iteratoropération est effectuée, la méthode compare les deux valeurs de compteur et lance un CME si elles sont différentes.

En revanche, les itérateurs faiblement cohérents sont généralement légers et tirent parti des propriétés des structures de données internes de chaque collection simultanée. Il n'y a pas de modèle général. Si vous êtes intéressé, lisez le code source des différentes classes de collection.


1 - Le cavalier est que le comportement Fail-Fast suppose que l'application identifie correctement par rapport à la synchronisation et au modèle de mémoire. Cela signifie que (par exemple) si vous effectuez une itération ArrayListsans synchronisation appropriée, le résultat peut être un résultat de liste corrompu. Le mécanisme "d'échec rapide" détectera probablement la modification simultanée (bien que ce ne soit pas garanti), mais il ne détectera pas la corruption sous-jacente. À titre d'exemple, javadoc for Vector.iterator()dit ceci:

"Le comportement de défaillance rapide d'un itérateur ne peut pas être garanti car il est, d'une manière générale, impossible de faire des garanties concrètes en présence de modifications concurrentes non synchronisées. Les itérateurs rapides de défaillance lancent ConcurrentModificationExceptionsur la base du meilleur effort. Par conséquent, ce serait incorrect d'écrire un programme qui dépendait de cette exception pour son exactitude: le comportement rapide des itérateurs ne devrait être utilisé que pour détecter les bogues. "

Stephen C
la source
Peut-être un peu hors de propos mais pourrait également être complémentaire pour cette question. Qu'en est-il du style de cliché utilisé, par exemple, par le CoW? Plus précisément, je ne comprends pas tout à fait comment le tableau sous-jacent (ou l'instantané) sur lequel l'itérateur CoW itère "ne" voit pas les modifications apportées par d'autres threads car nous sommes toujours en mesure d'appeler setArrayn'importe quelle modification.
stdout
J'ai décidé que parler de l'implémentation d'itérateurs faiblement cohérents sortait du cadre de cette Q&R.
Stephen C
42

Ce sont des types plutôt rapides et faiblement cohérents :

Les itérateurs du java.utilpackage lancent ConcurrentModificationExceptionsi la collection a été modifiée par les méthodes de la collection (ajouter / supprimer) lors de l'itération

Les itérateurs du java.util.concurrentpackage itèrent généralement sur un instantané et autorisent des modifications simultanées, mais peuvent ne pas refléter les mises à jour de la collection après la création de l'itérateur.

Evgeniy Dorofeev
la source
Iterator est un exemple de restauration rapide alors que l'énumération est sécurisée
Ajay Sharma
5
@AjaySharma - Incorrect sur deux points. 1) Ni l'un Iteratorni l' autre ou ne Enumerationspécifiez le comportement comme fail-fast ou fail-safe. Ce sont des implémentations spécifiques (c'est-à-dire les méthodes spécifiques de la collection iterator()/ elements()etc qui retournent ces objets) qui spécifient le comportement. 2) Les implémentations typiques d'énumération ne sont ni rapides ni sûres .
Stephen C
22

La seule différence est que l'itérateur de sécurité ne lance aucune exception, contrairement à l'itérateur rapide.

Si la collection est modifiée structurellement pendant qu'un thread l'itère. En effet, ils fonctionnent sur le clone de la collection au lieu de la collection originale et c'est pourquoi ils sont appelés itérateur de sécurité.

Iterator of CopyOnWriteArrayList est un exemple d'itérateur à sécurité intégrée également un itérateur écrit par ConcurrentHashMap keySet est également un itérateur à sécurité intégrée et ne lance jamais ConcurrentModificationException en Java.

Juned Ahsan
la source
Je ne vois pas que l'itérateur ConcurrentHashMap fonctionne sur clone () .. :( Parfois, il reflétera certaines mises à jour lors de l'itération ..
Kanagavelu Sugumar
0

Ce scénario concerne le "traitement simultané", ce qui signifie que plus d'un utilisateur accède à la même ressource. Dans une telle situation, l'un des utilisateurs essaie de modifier cette ressource, ce qui cause l'exception «ConcurrentProcessingException» car dans ce cas, d'autres utilisateurs obtiennent des données incorrectes. Ces deux types se rapportent à ce genre de situation.

En termes simples,

Échec rapide:

  • Les itérateurs lèvent immédiatement ConcurrentModificationException si une modification structurelle (ajout, mise à jour, suppression) se produit.
  • Exemple: ArrayList, HashMap, TreeSet

Fail-Safe:

  • Ici, les itérateurs ne lancent aucune exception car ils opèrent sur le clone de la collection, pas sur l'original. Donc, ce sont des itérateurs à sécurité intégrée.
  • Exemple: CopyOnWriteArrayList, ConcurrentHashMap
Dhwanil Patel
la source