Roadmap › How Computers Work — CPU, Memory, OS, Processes and Threads › Module: Operating System, Processes and Threads
Lessons in this course (11)

9. Concurrency problems — race conditions, deadlocks and how to avoid them

Intermediate★ Must knowLesson 9 of 11

Concurrency = several tasks in progress at once (may interleave on one core). Parallelism = tasks literally running at the same time on several cores.

ProblemWhat happensFix
Race conditionTwo threads read-modify-write shared data; updates get lostLocks, atomic operations (Interlocked), immutable data, don't share
DeadlockThread A holds lock 1 waiting for lock 2; B holds 2 waiting for 1 — both wait foreverAlways lock in the same order, use timeouts, keep locks short
StarvationA thread never gets the resourceFair locks, priorities
LivelockThreads keep reacting to each other without progressBack-off with randomness
Thread-pool starvationAll pool threads blocked (e.g. .Result on async)Async all the way
csharp
int counter = 0;
Parallel.For(0, 1_000_000, _ => counter++);              // ❌ race: result is less than 1,000,000
Console.WriteLine(counter);

int safe = 0;
Parallel.For(0, 1_000_000, _ => Interlocked.Increment(ref safe));   // ✅ atomic
var gate = new object();
lock (gate) { /* only one thread at a time here */ }      // ✅ mutual exclusion

The same ideas appear in databases: SQL Server uses locks and isolation levels to stop concurrent transactions corrupting data, and can deadlock too (it then kills one transaction as the victim).