Search code examples
c#multithreadingthread-safetylock-freeconcurrency

How to create a Lockfree collection of collection


I need to create a collection of collections. The collection is called by multiple threads to add items and lookup items. Once added the items will not be removed. Currently, while adding elements I need to take a lock on the entire collection. Is there a way around it to make it lockfree. Or is there a better datastructure or pattern that I can use? Here is a simplified version of my code:

readonly ConcurrentDictionary<string, ConcurrentDictionary<int, int>> dict = new ConcurrentDictionary<string, ConcurrentDictionary<int, int>>();

void AddUpdateItem(string s, int k, int v)
{
    ConcurrentDictionary<int, int> subDict;
    if (dict.TryGetValue(s, out subDict))
    {
        subDict[k] = v;
    }
    else
    {
        lock (dict)
        {
            if (dict.TryGetValue(s, out subDict))
            {
                subDict[k] = v;
            }
            else
            {
                subDict = new ConcurrentDictionary<int, int>();
                subDict[k] = v;
                dict[s] = subDict;
            }
        }
    }
}

Solution

  • Method ConcurrentDictionary.GetOrAdd is thread safe (although not atomic). It guarantees that the returned object is the same for all threads. Your code could be rewritten as:

    void AddUpdateItem(string s, int k, int v)
    {
        var subDict = dict.GetOrAdd(s, _ => new ConcurrentDictionary<int, int>());
        subDict[k] = v;
    }