8
votes

C # Liste simultanée Questions

J'ai une situation en C # où j'ai une liste de types simples. Cette liste est accessible par plusieurs threads: les entrées peuvent être ajoutées ou supprimées et l'existence d'une entrée peut être vérifiée. J'ai encapsulé la liste dans un objet exposant à ces trois opérations jusqu'à présent.

J'ai quelques cas à gérer (pas exactement les mêmes que les méthodes que je viens de mentionner).

  1. Un thread peut simplement vérifier l'existence d'une entrée. (simple)
  2. Un thread peut vérifier l'existence d'une entrée et s'il n'existe pas, ajoutez-le.
  3. Un fil doit vérifier si une entrée existe et si elle le fait, attendez qu'il soit supprimé.
  4. Une combinaison de 2 et 3, où un thread vérifie l'existence d'une entrée, si elle existe, il doit attendre qu'il soit retiré avant de pouvoir l'ajouter lui-même.

    L'idée entière est que l'existence d'une entrée signifie une serrure. Si une entrée existe, l'objet qu'il identifie ne peut pas être modifié et que le code ne peut pas continuer, car il est modifié ailleurs.

    Ceux-ci peuvent sembler des situations novices simples, mais je me rafraîchis sur des problèmes de concurrence et cela me rend un peu paranoïaque, et je ne suis pas aussi familier avec les mécanismes de concurrence de C #.

    Quelle serait la meilleure façon de gérer cela? Suis-je totalement éteint? Devrait vérifier et ajouter (test et définir?) Être combiné dans une quatrième opération atomique? Serais-je simplement ajouter des blocs de verrouillage à mes méthodes où la liste est accessible?

    Aussi, est-il possible de tester un appareil à tester ce genre de chose (pas les opérations simples, les situations de concurrence)?


0 commentaires

4 Réponses :


8
votes

Les tests unitaires seront certainement difficiles.

Cela peut tous être fait raisonnablement simplement avec les mécanismes de concurrence "natifs" dans .NET: relevés de verrouillage et moniteur.wait / moniteur. Pulseall . Sauf si vous avez un moniteur séparé par article, vous devrez réveiller tous les discussions chaque fois que tout est supprimé - sinon vous ne pourrez pas dire au fil "droit" de se réveiller. < p> Si ce n'est vraiment qu'un défini d'éléments, vous pouvez utiliser hashset au lieu de la liste pour représenter La collection, au fait - rien que vous avez mentionné est de faire avec la commande.

code d'échantillon, en supposant qu'un ensemble est correct pour vous: xxx < P> (complètement non testé, certes. Vous voudrez peut-être aussi spécifier des délais d'attente pour le code d'attente ...)


1 commentaires

+1, je suis venu à une solution similaire, mais le hashset le rend plus efficace. Belle démo pour la classe de surveillance, à l'aide de verrous imbriquées, etc. Seul problème pourrait être un «Stampede» lorsqu'un élément est supprimé.



8
votes

tandis que # 1 peut être le plus simple à écrire, c'est essentiellement une méthode inutile. Sauf si vous retenez la même serrure après avoir terminé une requête pour "existence d'une entrée", vous retournez "l'existence d'une entrée à un moment donné dans le passé". Cela ne vous donne aucune information sur l'existence actuelle de l'entrée.

Entre la découverte d'une valeur dans la liste, effectuez une opération de récupération, supprimez la valeur, un autre thread pourrait venir le supprimer pour vous.

contient des opérations sur une liste simultanée devrait être combinée à l'opération que vous prévoyez de faire dans le cas d'une existence véritable / fausse de cette vérification. Par exemple, Testaddd () ou TestReMove () est beaucoup plus sûr que contenant + Ajouter ou contient + Supprimer


7 commentaires

Vous devez créer un lien vers votre poteau de blog sur les interfaces de collection de fil de fil.


Oui, mais # 4 fait exactement ça. La convivialité des autres méthodes est douteuse, mais pas nécessairement fausse.


@Henk, je pense que # 2- # 4 sont de bonnes méthodes. # 1 si ce n'est pas faux mais ce n'est tout simplement pas utile.


Eh bien, voici la chose. Il y a quelques cas où si une entrée existe, je dois simplement sauter du code et continuer.


@Matt, le problème est que vous ne pouvez pas penser à l'élément comme existant. Vous devez y penser comme «utilisé pour avoir existé»


D'accord, alors que dois-je faire à la place? Le scénario dont je parle est l'endroit où un utilisateur peut verrouiller manuellement un objet lors de la modification, mais une demande de modification peut être utilisée pour le même objet, et elle devrait être ignorée. Seulement si l'objet n'est pas verrouillé si la demande de mise à jour soit traitée.


@Matt, je ne suis pas tout à fait sûr que je comprenne le scénario mais que j'aurais un essai suffisant?



1
votes

Il existe un produit pour trouver des conditions de course et tels que les tests d'unité. C'est ce qu'on appelle Typemock Racer . Je ne peux rien dire pour ou contre son efficacité, cependant. :)


0 commentaires

2
votes

Voici une implémentation appropriée, simultanée de la liste simultanée, parallèle http://www.deandalchalk.me.uk/post /Task-parallel-concurrent-list-Implementalation.aspx


1 commentaires

Non, cette mise en œuvre est complètement non-fil sûre pour énumérer et le verrouillage excessif en fait un mauvais choix.