What is a race condition?
Why Interviewers Ask This
This question tests conceptual clarity. Interviewers want to hear a precise, confident definition before moving to more complex Operating Systems topics. It also reveals how well you can explain technical ideas to non-experts.
Answer
A race condition occurs when the outcome of a program depends on the relative timing or interleaving of operations by multiple threads/processes accessing shared data — and that timing leads to incorrect behavior. The "race" is between threads to access shared state first, and the wrong order causes bugs. Classic example: // Two threads both incrementing a shared counter: Thread A: Thread B: LOAD counter (0) LOAD counter (0) ADD 1 (1) ADD 1 (1) STORE counter (1) STORE counter (1) // Result: counter = 1, but should be 2! // Thread A's write was lost. The counter++ operation is NOT atomic — it's three separate assembly instructions (LOAD, ADD, STORE). If a context switch happens between them, data is corrupted. Race condition vs data race: data race = concurrent access to the same memory location with at least one write and no synchronization. All data races are race conditions, but not all race conditions are data races (logic races don't involve memory). Detecting: ThreadSanitizer (TSan) compiler flag (-fsanitize=thread) instruments code to detect data races at runtime. Helgrind (Valgrind tool). Preventing: mutex locks around critical sections; atomic operations (std::atomic, AtomicInteger); lock-free data structures; message passing (avoid shared state); immutable data. Heisenbugs: race conditions often disappear when adding debugging output (changes timing) — notoriously hard to reproduce and fix. Always reproduce with TSan/Helgrind before fixing.
Pro Tip
Before answering, structure your response: one-line definition → real-world analogy → concrete example from a project. This makes even complex Operating Systems answers easy to follow.