What is the difference between Dictionary and ConcurrentDictionary?

C# Collections Intermediate 2–3 Yrs3–5 Yrs Conceptual 1 min read

Quick Answer

Dictionary<K,V> is not thread-safe — concurrent writes (or a write during a read) corrupt it or throw. ConcurrentDictionary<K,V> is thread-safe with fine-grained locking and atomic operations like GetOrAdd, AddOrUpdate, TryUpdate. Use it for shared caches; use a plain Dictionary for single-threaded or read-only-after-build data.

A plain Dictionary isn't thread-safe — if two threads write at once, or one writes while another reads, you can corrupt the internal state or get an exception. ConcurrentDictionary handles that with lock striping and gives you atomic helpers like GetOrAdd and AddOrUpdate. The subtlety with GetOrAdd is that the value factory can run twice under contention even though only one value wins, so I keep the factory cheap or wrap the value in a Lazy. For data that's built once and then only read, a normal dictionary is faster.

  • GetOrAdd(key, factory) is atomic for the dictionary, but the factory can run more than once under contention (only one result is kept) — make the factory cheap or idempotent, or use Lazy<T> as the value.
  • Enumerating a ConcurrentDictionary gives a moment-in-time snapshot and won't throw during concurrent writes.
  • Count and ToArray take all internal locks — avoid in hot paths.
  • For read-heavy, build-once data, a plain Dictionary (or FrozenDictionary in .NET 8) is faster.