Deadlock
Concurrency: lesson 4 of 10
Everyone holding what the next one needs.
Lesson 4 of 10 · 5 min
Deadlock
Step 1 of 10
Two threads, two locks, and each thread needs both before it can finish its transfer.
The Idea
Deadlock is a standoff. Thread one holds lock A and wants B; thread two holds B and wants A. Neither will let go of what it has, so both wait forever. No exception is raised — the work simply stops.
Real-World Example
Two joinery apprentices glueing a frame. One has the clamp and needs the glue; the other has the glue and needs the clamp. Both stand there holding their half, each perfectly reasonably waiting for the other to finish first.
The Tradeoff
Fine-grained locks buy real parallelism and hand you the possibility of a cycle. Imposing one global acquisition order removes the cycle and costs nothing at runtime. Timeouts are the fallback: they convert a permanent hang into a retry, which is a friendlier bug but still a bug.
import threading
locks = {"alice": threading.Lock(), "bob": threading.Lock()}
def transfer(src, dst):
first, second = sorted([src, dst]) # always the same order
with locks[first], locks[second]:
print("moved", src, "->", dst)
transfer("bob", "alice")
transfer("alice", "bob") # no cycle: alice's lock goes first
Your turn
Put the steps in the right order.
- Thread 1 requests lock B, which Thread 2 holds, and blocks
- Thread 1 acquires lock A
- Both threads wait forever, each holding what the other needs
- Thread 2 acquires lock B
Mini quiz
1 / 3