2010-04-11 3 views
4

Cette question concerne à la fois C# et JavaItère Collection Dans deux fils

Si vous avez une collection qui n'est pas modifiée et que la référence de collecte est partagé entre deux fils ce qui se passe lorsque vous itérer sur chaque thread ??

ThreadA: Collection.iterator ThreadA: Collection.moveNext ThreadB: Collection.iterator ThreadB: Collection.moveNext

Will ThreadB voir le premier élément?

L'itérateur est-il toujours réinitialisé lorsqu'il est demandé? Que se passe-t-il si cela est entrelacé, de sorte que movenext et l'élément sont entrelacés? Y a-t-il un danger que vous ne traitiez pas tous les éléments?

+0

Il est préférable d'utiliser une BlockingQueue en Java. Ceci est conçu pour être partagé à travers un nombre quelconque de threads et peut être modifié pendant que vous lisez. –

+0

Op's Q en un mot: "Est-ce que chaque itérateur de la même collection agit indépendamment les uns des autres?" –

Répondre

3

Cela fonctionne comme prévu, car chaque fois que vous demandez l'itérateur, vous en obtenez un nouveau.

Si ce n'était pas le cas, vous ne seriez pas en mesure de faire foreach suivi de foreach sur la même collection!

+0

Comment fait-il cela par intérêt? Savez-vous –

+0

zihotki posté quelques bons liens.En C# il est facile de voir comment cela fonctionne, ajoutez simplement IEnumerable à l'une de vos classes et demandez-lui d'implémenter l'interface - vous verrez qu'il ajoute "public IEnumerator GetEnumerator()" de sorte que vous devez fournir un objet qui implémente IEnumerator - alors maintenant en faire un et voir ce qu'il y a dedans. Chaque requête à GetEnumerator obtient un nouvel objet qui suit l'énumération. –

1

En Java (et je suis presque sûr en C#), les collections d'API standard n'ont généralement pas un seul itérateur. Chaque appel à iterator() produit un nouveau, qui a son propre index ou pointeur interne, de sorte que tant que les deux threads acquièrent leur propre objet itérateur, il ne devrait y avoir aucun problème. Cependant, ceci n'est pas garanti par l'interface, et la capacité de deux itérateurs à fonctionner simultanément ne pose aucun problème. Pour les implémentations personnalisées de collections, tous les paris sont désactivés.

2

Par convention, un Iterator est implémenté de sorte que l'action de traversée n'altère jamais l'état de la collection. Il pointe uniquement vers la position actuelle dans la collection et gère la logique d'itération. Par conséquent, si vous numérisez la même collection par N threads différents, tout devrait fonctionner correctement.

Toutefois, notez que Iterator Java permet suppression des articles et ListIterator soutient même l'opération mis. Si vous souhaitez utiliser ces actions par au moins l'un des threads, vous devrez probablement faire face à des problèmes de concurrence (ConcurrentModificationException), sauf si l'Iterator est spécifiquement conçu pour de tels scénarios (comme avec les itérateurs de ConcurrentHashMap).

0

Au moins en C#, toutes les collections standard peuvent être énumérées simultanément sur différents threads. Cependant, l'énumération sur n'importe quel thread explosera si vous modifiez la collection sous-jacente pendant l'énumération (comme il se doit). Je ne crois pas qu'un développeur sensé qui écrit une classe de collection permette à ses énumérateurs de muter l'état de collection de manière à interférer avec l'énumération mais c'est possible Toutefois, si vous utilisez une collection standard, vous pouvez le supposer en toute sécurité et utiliser des stratégies de verrouillage telles que Single Writer/Multiple Reader lors de la synchronisation de l'accès aux collections.