web-dev-qa-db-fra.com

Quand ConcurrentDictionary TryRemove retournera false

Renverra-t-il uniquement false si le dictionnaire ne contient pas de valeur pour la clé donnée ou renverra-t-il également false en raison des conditions de concurrence du thread, comme un autre thread ajoute/met à jour quelque chose?

Question dans le code:

ConcurrentDictionary<int, string> cd = new ConcurrentDictionary<int, string>();

// This might fail if another thread is adding with key value of 1.
cd.TryAdd(1, "one"); 

// Will this ever fail if no other thread ever removes with the key value of 1?
cd.TryRemove(1); 

Edit: Je pense que cela ne retournera false que s'il ne contient pas de valeur pour la clé donnée, mais je veux être absolument sûr.

Alors que Mitch a raison qu'un ConcurrentDictionary n'est pas vulnérable aux conditions de concurrence, je pense que la réponse à la question que vous posez est que oui, si la clé est présente, TryRemove fonctionnera et renverra true.

Dans le code que vous avez publié, il n'y a aucun moyen que TryRemove renvoie false puisque cd est une variable locale qui n'est accessible nulle part ailleurs. Mais si du code ailleurs a été référencé à cet objet ConcurrentDictionary et a supprimé des clés sur un thread séparé, il est possible que TryRemove puisse retourner false, même ici - mais uniquement parce que la clé a déjà été supprimée , pas parce qu'une autre action est en cours d'exécution sur le dictionnaire et que la clé y est "bloquée".

74
Dan Tao

Le ConcurrentDictionary ne souffre pas de conditions de course. C'est pourquoi vous l'utilisez.

Valeur de retour

true si un objet a été supprimé avec succès; sinon, faux.

6
Mitch Wheat

Un autre point à souligner:

// This might fail if another thread is adding with key value of 1.
cd.TryAdd(1, "one"); 

Ce commentaire est incorrect et souffre peut-être de la même idée fausse sur ce que signifie "essayer". Il ne s'agit pas d'une tentative d'ajout simultanée, c'est de savoir si une valeur a déjà été ajoutée avec la clé 1.

Considérez une norme Dictionary<TKey,TValue>. Le code équivalent serait:

if (!d.Contains(1))
    d.Add(1, "one");

Cela nécessite deux opérations. Il n'y a aucun moyen de concevoir une telle API pour être threadsafe, car cd peut avoir une valeur avec la clé 1 ajouté entre l'appel à Contains et Add, ce qui entraînerait alors le lancement de Add.

Les collections simultanées ont des API qui regroupent logiquement ces paires test-et-do en opérations atomiques uniques, derrière une seule API.

1
Drew Noakes