Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lock for ConcurrentDictionary when AddOrUpdate-ing?

I use a ConcurrentDictioanry<string, HashSet<string>> to access some data across many threads.

I read in this article (scroll down) that the method AddOrUpdate is not executed in the lock, so it could endanger thread-safety.

My code is as follows:

//keys and bar are not the concern here
ConcurrentDictioanry<string, HashSet<string>> foo = new ...;
foreach(var key in keys) {
    foo.AddOrUpdate(key, new HashSet<string> { bar }, (key, val) => {
        val.Add(bar);
        return val;
    });
}

Should I enclose the AddOrUpdate call in a lock statement in order to be sure everything is thread-safe?

like image 905
Paul Avatar asked Sep 13 '12 20:09

Paul


1 Answers

Locking during AddOrUpdate on its own wouldn't help - you'd still have to lock every time you read from the set.

If you're going to treat this collection as thread-safe, you really need the values to be thread-safe too. You need a ConcurrentSet, ideally. Now that doesn't exist within the framework (unless I've missed something) but you could probably create your own ConcurrentSet<T> which used a ConcurrentDictionary<T, int> (or whatever TValue you like) as its underlying data structure. Basically you'd ignore the value within the dictionary, and just treat the presence of the key as the important part.

You don't need to implement everything within ISet<T> - just the bits you actually need.

You'd then create a ConcurrentDictionary<string, ConcurrentSet<string>> in your application code, and you're away - no need for locking.

like image 125
Jon Skeet Avatar answered Sep 28 '22 03:09

Jon Skeet