← Back to CS Fundamentals

Thread Safety — Is dict Thread Safe?

CS FundamentalsSenior

The Question

What does thread safety mean? Is Python's dict thread-safe?

What a Strong Answer Covers

  • individual ops safe due to GIL
  • "compound ops not safe
  • "GIL protects interpreter not user code

Senior-Level Answer

Thread safety means that a data structure or piece of code produces correct results when accessed concurrently by multiple threads, without requiring the caller to perform external synchronization. A thread-safe operation is one where concurrent invocations cannot interleave in a way that corrupts state or produces incorrect output.

Python's dict has a nuanced safety story tied to the Global Interpreter Lock (GIL). The GIL ensures that only one thread executes Python bytecode at a time, which means individual dict operations like __getitem__, __setitem__, and __delitem__ are atomic at the bytecode level. You will not get a segfault or a corrupted internal structure from concurrent reads and writes. In that narrow sense, built-in dict operations are GIL-protected.

However, GIL-atomicity does not mean thread-safe for compound operations. Consider d[key] += 1: this compiles to a LOAD, ADD, STORE sequence -- three bytecode instructions. The GIL can be released between any of these, so two threads can both read the old value, both increment it, and both write back the same incremented value, losing one update. This is a classic lost-update race condition.

Additionally, iterating over a dict while another thread modifies it will raise a RuntimeError: dictionary changed size during iteration. Python intentionally detects this rather than silently producing wrong results.

For truly thread-safe dict operations, you have several options. threading.Lock or threading.RLock can guard compound operations. The collections module does not provide a thread-safe dict directly, but queue.Queue is thread-safe for producer-consumer patterns. In Python 3.7+ you can also use concurrent.futures or high-level abstractions that avoid shared mutable state entirely.

The takeaway for interviews: dict is safe from corruption at the interpreter level due to the GIL, but it is not thread-safe for compound operations or iteration under concurrent modification. Never rely on GIL-atomicity as a substitute for explicit synchronization when correctness depends on multi-step operations.

What Separates a 2/3 from a 3/3

2/3 — Passing but Incomplete

Candidate knows the GIL prevents corruption on individual operations and mentions that compound operations like += are not atomic, but does not explain why (multiple bytecodes) or give concrete safe alternatives.

3/3 — Strong Answer

Candidate explains GIL-atomicity at the bytecode level, correctly identifies compound operations and iteration as unsafe, names specific race conditions (lost update, RuntimeError on iteration), and mentions explicit locking or lock-free alternatives.

Common Mistakes

  • Claiming dict is fully thread-safe because of the GIL -- the GIL only protects single bytecode operations, not compound ones
  • Not knowing that d[k] += 1 is multiple bytecode instructions and thus not atomic
  • Forgetting that iteration raises RuntimeError if the dict is modified concurrently
  • Confusing thread safety with the absence of crashes -- correctness under concurrency is the actual bar

Follow-Up Questions

  • How would you make a thread-safe counter in Python? — Use threading.Lock around the read-modify-write, or use threading.local for per-thread counts, or avoid shared state entirely.
  • What is the difference between atomicity and thread safety? — Atomicity means an operation completes without interruption; thread safety is the broader guarantee that concurrent access produces correct results.
  • Would removing the GIL make dict operations fully thread-safe? — No -- without the GIL you would need explicit internal locking inside dict to prevent corruption even on single operations.
  • How does dict subclassing affect thread safety? — Subclasses may override methods with pure Python code, losing GIL-atomicity on those operations -- even less safe than the built-in dict.

Related Questions

  • Process vs Thread
  • Race Condition
  • Deadlock — 4 Conditions, Prevention
  • HashMap Internals
  • Hash Collision — Chaining vs Open Addressing

Can You Explain This Cold?

Reading the answer is step one. Explaining it unprompted — under interview pressure — is what actually matters. Get AI-graded feedback on your answer with follow-up probes on your weak points.

Get Graded — Free Assessment
GrindQuestionsAITechnical interview assessment
TermsPrivacyAbout