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;
}
}
}
}
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;
}