Search code examples
c#multithreadingcollectionsdictionarydouble-checked-locking

Double checked locking on Dictionary "ContainsKey"


My team is currently debating this issue.

The code in question is something along the lines of

if (!myDictionary.ContainsKey(key))
{
    lock (_SyncObject)
    {
        if (!myDictionary.ContainsKey(key))
        {
            myDictionary.Add(key,value);
        }
    }
}

Some of the posts I've seen say that this may be a big NO NO (when using TryGetValue). Yet members of our team say it is ok since "ContainsKey" does not iterate on the key collection but checks if the key is contained via the hash code in O(1). Hence they claim there is no danger here.

I would like to get your honest opinions regarding this issue.


Solution

  • Don't do this. It's not safe.

    You could be calling ContainsKey from one thread while another thread calls Add. That's simply not supported by Dictionary<TKey, TValue>. If Add needs to reallocate buckets etc, I can imagine you could get some very strange results, or an exception. It may have been written in such a way that you don't see any nasty effects, but I wouldn't like to rely on it.

    It's one thing using double-checked locking for simple reads/writes to a field, although I'd still argue against it - it's another to make calls to an API which has been explicitly described as not being safe for multiple concurrent calls.

    If you're on .NET 4, ConcurrentDictionary is probably the way forward. Otherwise, just lock on every access.