I have a ConcurrentDictionary which maps a simple type to a list:
var dict = new ConcurrentDictionary<string, List<string>>();
I can use AddOrUpdate() to cater for both initialization of the list when the first value is added, and addition of subsequent values to the list.
However, the same isn't true for removal. If I do something like:
public void Remove(string key, string value)
{
List<string> list;
var found = dict.TryGetValue(key, out list);
if (found)
{
list.Remove(value);
if (list.Count == 0)
{
// warning: possible race condition here
dict.TryRemove(key, out list);
}
}
}
...where my intention is to remove the key completely if the corresponding list no longer has any values (similar to reference counting, in concept), then I'm risking a race condition because someone might have added something to the list right after I checked whether it's empty.
Although I am using a list in this simple example, I usually have a ConcurrentBag or ConcurrentDictionary in such scenarios, and the risk is quite similar.
Is there any way of safely removing a key when the corresponding collection is empty, short of resorting to locks?