Concurrency — Locks, Deadlocks, Sync/Async, Blocking/Non-blocking
Concurrency — Locks, Deadlocks, Sync/Async, Blocking/Non-blocking
🎯 After reading this lesson
After finishing this lesson, you will be able to confidently handle the following three topics.
- ▸✅ Mutex vs Semaphore vs Monitor
- ▸✅ Race Condition + 4 conditions for Deadlock
- ▸✅ Sync vs Async + Blocking vs Non-blocking — all 4 combinations
Keep the learning objectives as a checklist, and close the lesson once you can answer all of them.
Race Condition — The Tragedy of Concurrent Modification
In one line: Two threads modifying the same data simultaneously → unpredictable result.
Example:
Reason: counter + 1 involves 3 instructions:
1. read counter → register
2. register + 1
3. register → counter
If A executes steps 1 and 2, then B executes step 1 → both read 0, add 1, and only 1 gets stored.
Solutions:
Common race condition traps:
- ▸❌ Bug disappears when you attach a debugger (Heisenbug) — the debugger changes timing
- ▸❌ "Works on my machine" — different number of CPU cores or load
- ▸✅ Always run concurrency tests (
-raceflag, ThreadSanitizer)
Mutex — The Most Common Lock
Mutex (MUTual EXclusion): Only one thread at a time may enter the critical section.
Usage flow:
Mutex by language:
Common mutex mistakes:
ReadWriteLock: Multiple concurrent readers + exclusive writer → advantageous for read-heavy workloads.
Optimistic Lock: Commonly used in databases. Retry on conflict (similar to CAS).
Deadlock — Waiting Forever
4 necessary conditions (deadlock occurs when all are met):
1. Mutual Exclusion — A resource can be held by only one thread at a time
2. Hold and Wait — A thread holds a resource while waiting for another
3. No Preemption — Resources cannot be forcibly taken away
4. Circular Wait — A → B → C → A cycle
Classic example: Two threads acquire the same two locks in different orders:
→ Thread 1 holds A and waits for B / Thread 2 holds B and waits for A → neither proceeds
6 solutions:
Deadlock debugging:
- ▸Java:
jstack <PID>→ automatically detects "Found one Java-level deadlock" - ▸Python:
faulthandler+ thread dump - ▸Go:
go run -race(race detector) - ▸DB: PostgreSQL auto-detects and aborts the victim transaction
Sync vs Async · Blocking vs Non-blocking
4 combinations (frequently confused — understand each separately):
Sync/Async = how completion is notified
Blocking/Non-blocking = whether the caller can proceed
4 Linux I/O models:
How epoll works (efficient I/O multiplexing on Linux):
1. epoll_create() — create an instance
2. epoll_ctl(ADD) — register file descriptors to watch
3. epoll_wait() — block until an event fires
4. Handle the fd → wait again
Why Node.js and Nginx are fast = single thread + epoll event loop → no context switching.
🤖 Try asking AI like this
Knowing the concepts in this lesson lets you give AI specific instructions.
- ▸"Analyze the concurrency issues in this method and recommend synchronized vs ReentrantLock."
- ▸"This code might have a deadlock — diagnose it by examining the resource acquisition order."
- ▸"Parallelize this task using CompletableFuture + thenCombine."
Why this reduces token usage
Knowing vocabulary like "lock / deadlock / volatile / atomic" means AI responses come back as direct code. Without it, you get a "what is concurrency..." explanation first.