liveBook · Manning

ConcurrentDictionary<TKey,TValue>

As explained in C# Concurrency: Asynchronous and multithreaded programming

ConcurrentDictionary<TKey,TValue> is a .NET thread-safe generic key-value collection that supports concurrent access and atomic conditional updates.

ConcurrentDictionary<TKey,TValue> is a thread-safe alternative to Dictionary<TKey,TValue> for key-value access from multiple threads. Its concurrent collections use fine-grained locking and lockless techniques, while its interface combines operations that commonly belong together to avoid race conditions. section 13.2 section 13.5

Use conditional operations instead of separating a check from its update:

  • TryGetValue reads an existing value and reports whether the key was found. section 13.2.1
  • TryAdd inserts a value and returns false when another thread has already added the key, treating that race as a normal result rather than an exception. section 13.2.1
  • GetOrAdd combines lookup and creation for an in-process cache: var item = dictionary.GetOrAdd(itemId, CreateAndInitializeItem). section 13.2.1
  • TryUpdate supports compare-and-update logic; retry until it succeeds when incrementing a value concurrently. section 13.2.1

Concurrent increment

private ConcurrentDictionary<string, int> _dictionary = new(); public void Increment(string key) { while (true) { int prevValue = _dictionary[key]; if (_dictionary.TryUpdate(key, prevValue + 1, prevValue)) break; } } The expected previous value acts as a condition: a competing update causes TryUpdate to fail, so the loop rereads and retries. section 13.2.1

Listing 13.8 Thread-safe cache with ConcurrentDictionary.GetOrAdd
var item = dictionary.GetOrAdd(itemId,CreateAndInitializeItem);

Browse the compact cache implementation using GetOrAdd. section 13.2.1

How C# Concurrency: Asynchronous and multithreaded programming covers it

How deep it goes
Explains thread-safety mechanisms and demonstrates conditional lookup, insertion, retrieval-or-creation, and retrying updates.
Examples
Uses an in-process cache and a concurrently incremented integer dictionary.
What it assumes
Assumes familiarity with Dictionary<TKey,TValue> and multithreaded access while teaching the race-safe alternatives from the basic cache pattern.
What you can do after
Apply it via TryAdd, GetOrAdd, and TryUpdate to build thread-safe caches and conditional concurrent updates.
How it connects
Connects Dictionary<TKey,TValue>, race conditions, locks, concurrent collections, and asynchronous programming.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of C# Concurrency: Asynchronous and multithreaded programming. The section links point to the parts of the book it draws on.