ConcurrentDictionary
Learn the thread-safe dictionary with ConcurrentDictionary.
ConcurrentDictionary
ConcurrentDictionary<TKey, TValue> is a dictionary that multiple threads can safely read and write. Reads take no lock; writes take a separate fine-grained lock per bucket.
So it runs faster than guarding a plain Dictionary with lock. Atomic methods like GetOrAdd and AddOrUpdate remove the check-then-add race condition.
GetOrAdd and AddOrUpdate
GetOrAdd(key, value) adds the key if absent and returns its value; if present it returns the existing value without overwriting.
AddOrUpdate(key, addValue, updateFactory) adds addValue when absent, or computes a new value with updateFactory from the old one when present. For counters, a factory like (key, n) => n + 1 is very handy.
Exercise Count with ConcurrentDictionary
The counts dictionary below is empty. Use GetOrAdd to add three keys: "apple" = 3, "banana" = 5, "cherry" = 2. Then sort keys alphabetically with OrderBy(k => k.Key) and print each row as $"{kvp.Key}: {kvp.Value}".
Show example solution
{kvp.Value}");
Example solution:
using System;
using System.Collections.Concurrent;
using System.Linq;
class Program
{
static void Main()
{
var counts = new ConcurrentDictionary<string, int>();
counts.GetOrAdd("apple", 3);
counts.GetOrAdd("banana", 5);
counts.GetOrAdd("cherry", 2);
foreach (var kvp in counts.OrderBy(k => k.Key))
{
Console.WriteLine($"{kvp.Key}: {kvp.Value}");
}
}
}
Test yourself
-
Which method atomically adds a key if absent and returns the existing value if present?
- Add
- GetOrAdd
- TryAdd
- Put
Show answer
GetOrAdd — Correct. GetOrAdd atomically adds if absent or returns the existing value.
-
Complete the GetOrAdd call
counts.____;Show answer
counts.GetOrAdd("apple", 3); -
Match each method to its behavior
- GetOrAdd
- Add if absent, return existing
- AddOrUpdate
- Add if absent, update if present
- TryGetValue
- Check whether key exists