Wann gibt ConcurrentDictionary TryRemove false zurück?

79

Gibt es nur false zurück, wenn das Wörterbuch keinen Wert für den angegebenen Schlüssel enthält, oder gibt es aufgrund von Thread-Race-Bedingungen auch false zurück, wie wenn ein anderer Thread etwas hinzufügt / aktualisiert?

Frage im 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); 

Bearbeiten: Ich denke, dass es nur dann false zurückgibt, wenn es keinen Wert für den angegebenen Schlüssel enthält, aber absolut sicher sein möchte.

Martin Ingvar Kofoed Jensen
quelle

Antworten:

85

Während Mitch Recht hat, dass a ConcurrentDictionarynicht anfällig für Rennbedingungen ist, denke ich, dass die Antwort auf die Frage, die Sie stellen, lautet: Ja, wenn der Schlüssel vorhanden ist, TryRemovewird es funktionieren und zurückkehren true.

In dem von Ihnen geposteten Code gibt es keine Möglichkeit, TryRemovezurückzukehren, falseda cdes sich um eine lokale Variable handelt, auf die nirgendwo anders zugegriffen wird. Aber wenn ein Code an anderer Stelle einen Verweis auf diese gegeben wurde ConcurrentDictionaryObjekt und wurden Schlüssel auf einem separaten Thread zu entfernen, dann ist es möglich , die TryRemovezurückkehren konnte false, auch hier - aber nur , weil der Schlüssel bereits entfernt wurde , nicht weil eine andere Aktion durchgeführt wird auf Das Wörterbuch und der Schlüssel stecken dort irgendwie "fest".

Dan Tao
quelle
5

Das ConcurrentDictionary leidet nicht unter Rennbedingungen. Deshalb benutzt du es.

Rückgabewert

true, wenn ein Objekt erfolgreich entfernt wurde; sonst falsch.

Mitch Wheat
quelle
2

Ein weiterer Punkt zu machen:

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

Dieser Kommentar ist falsch und leidet möglicherweise unter dem gleichen Missverständnis darüber, was es bedeutet, es zu versuchen. Es geht nicht um einen gleichzeitigen Versuch, etwas hinzuzufügen, sondern darum, ob ein Wert bereits mit key hinzugefügt wurde 1.

Betrachten Sie einen Standard Dictionary<TKey,TValue>. Der entsprechende Code wäre:

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

Dies erfordert zwei Operationen. Es gibt keine Möglichkeit, eine solche API threadsicher zu gestalten, da zwischen dem Aufruf von und cdmöglicherweise ein Wert mit einem Schlüssel 1hinzugefügt wird , der dann zum Auslösen führen würde .ContainsAddAdd

Die gleichzeitigen Sammlungen verfügen über APIs, die diese Test-and-Do-Paare logisch zu einzelnen atomaren Operationen hinter einer einzelnen API bündeln.

Drew Noakes
quelle