Concurrency FundamentalsRace Conditions & Critical SectionsEasy⏱️ ~2 min

What is a Race Condition?

Definition
A race condition occurs when two or more threads access shared data concurrently, and at least one modifies it. The result depends on unpredictable execution order.

The ATM Problem

Two people withdraw money from the same account at different ATMs. Both check the balance ($100), both see enough funds, both withdraw $100. The bank loses money because the account goes negative. This is a race condition.

Race Condition: Lost Update
Thread AThread BCounterRead: 00Read: 0Write: 11Write: 11!
Expected: 2, Got: 1 - One increment lost!

Why Race Conditions Are Dangerous

Non-deterministic: Your code might work 1,000 times and fail on run 1,001. It depends on timing, CPU load, and factors you cannot control.

Hard to debug: Adding print statements changes the timing and makes the bug disappear. The bug hides when you look for it.

The Root Cause

Operations that look atomic in code are not atomic at the machine level. counter++ compiles to three instructions: load, add, store. Any of these can be interleaved with another thread.

Key Insight: If multiple threads access shared data and at least one writes, you have a potential race condition. Assume it will happen.
💡 Key Takeaways
Race conditions occur when multiple threads access shared data and at least one modifies it. The outcome depends on execution order.
Race conditions are non deterministic. The bug may appear once in 10,000 runs, making reproduction extremely difficult.
High level operations like counter++ are not atomic. They compile to multiple machine instructions that can interleave.
Race conditions cause data corruption, lost updates, and inconsistent state. Effects may not be visible until much later.
Adding debugging code (print statements) changes timing and can make race conditions disappear, making them even harder to find.
📌 Examples
1Two threads doing x = x + 1 where x starts at 0. Thread A reads 0, Thread B reads 0, Thread A writes 1, Thread B writes 1. Final value: 1 instead of 2.
2Check then act pattern: if (file.exists()) { file.delete(); }. Another thread could delete the file between check and act.
← Back to Race Conditions & Critical Sections Overview