76 votes

Quand est-ce que ConcurrentDictionary TryRemove retournera false ?

Renverra-t-il uniquement un message faux si le dictionnaire ne contient pas de valeur pour la clé donnée ou renverra-t-il également un message faux en raison de conditions de course de threads, par exemple si un autre thread ajoute/met à jour quelque chose ?

Question en 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 qu'il ne renverra que false s'il ne contient pas de valeur pour la clé donnée, mais je veux en être absolument sûr.

79voto

Dan Tao Points 60518

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

Dans le code que vous avez posté, il n'y a pas moyen que TryRemove rendrait false desde cd est une variable locale à laquelle on ne peut accéder nulle part ailleurs. Mais si une référence à cette variable locale était donnée à un autre code ailleurs ConcurrentDictionary et que vous supprimiez les clés sur un thread séparé, il est possible que l'objet TryRemove pourrait revenir false même ici mais seulement parce que la clé a déjà été retirée et non parce qu'une autre action est en cours sur le dictionnaire et que la clé y est en quelque sorte "bloquée".

5voto

Mitch Wheat Points 169614

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

Valeur de retour

vrai si un objet a été retiré avec succès avec succès ; sinon, faux.

3voto

Drew Noakes Points 69288

Une autre remarque à faire :

// 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 conception erronée de ce que signifie "essayer". Il ne s'agit pas d'une tentative d'ajout simultanée, mais de savoir si une valeur a déjà été ajoutée avec la clé 1 .

Considérons 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 qu'elle soit threadsafe, comme le montre le tableau ci-dessous. cd peut avoir une valeur avec une clé 1 ajouté entre l'appel à Contains y Add ce qui donnerait alors Add jetant.

Les collections concurrentes ont des API qui regroupent logiquement ces paires de tests et d'actions en opérations atomiques uniques, derrière une API unique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X