Concurrency in .NET: which tool when

A one-page map of .NET's concurrency tools, with the bugs each one prevents.

Concurrency in .NET: which tool when

When several threads touch the same data, three bugs appear: race conditions (lost updates), deadlocks (threads waiting on each other forever) and starvation (some work never gets a turn). Pick the tool that fits the situation.

Situation Tool Why
Add to a shared counter Interlocked atomic, no lock needed
Protect a few lines of sync code lock (on a private object, or Lock in .NET 9+) simple, fast; no await inside
Protect code that uses await SemaphoreSlim(1, 1) works with WaitAsync
Limit how many run at once SemaphoreSlim(n, n) lets n callers in
One lock across processes named Mutex visible to other processes
Many readers, few writers ReaderWriterLockSlim readers don’t block each other; not for async code
Shared dictionary or queue ConcurrentDictionary, ConcurrentQueue thread-safe operations
Hand work from producers to consumers Channel<T> async queue; a bounded one makes fast producers wait
Wait for I/O async/await no thread held while waiting

Rules that prevent most bugs

  • Share as little as possible. Immutable data needs no lock.
  • Keep locked blocks short, and never call unknown code (events, callbacks) while holding a lock.
  • Take locks in one fixed order to avoid deadlocks.
  • Don’t block on async code (.Result, .Wait()); in ASP.NET Core it starves the thread pool.
  • You can’t await inside a lock; use SemaphoreSlim.

Readers and writers

var rw = new ReaderWriterLockSlim();
var prices = new Dictionary<string, int> { ["tea"] = 3 };
rw.EnterReadLock(); try { Console.WriteLine(prices["tea"]); } finally { rw.ExitReadLock(); }
rw.EnterWriteLock(); try { prices["tea"] = 4; } finally { rw.ExitWriteLock(); }
Console.WriteLine(prices["tea"]);

It prints 3, then 4. Many threads can hold the read lock together; the write lock is exclusive. For short sections a plain lock is often just as fast.

Read more: https://learn.microsoft.com/en-us/dotnet/standard/threading/managed-threading-best-practices

#tip · TIP-082


Write a comment