The full picture
🎬 Deadlock: circular wait and the lock-ordering fix
1 / 5Two processes, two locks. P1 needs both the DB lock and the file lock to do its job; so does P2 — but they acquire them in OPPOSITE orders.
| Break this | How | Where you've seen it |
|---|---|---|
| Circular wait | global lock order (e.g., by account id) | the transfer(a,b) idiom; kernel lock ordering docs |
| Hold-and-wait | acquire all up front, or tryLock + release + retry | ReentrantLock.tryLock with jittered backoff |
| No preemption | victimize someone (rollback) | DB deadlock detectors killing a transaction |
| Mutual exclusion | don't lock: immutable / lock-free / single-writer | CAS counters, event-loop designs, actor models |
- Detection mechanics: build the waits-for graph, find a cycle, pick a victim (least work lost); that's InnoDB/Postgres behavior — application consequence: deadlock errors are retryable by design, so your data layer needs a retry policy for them.
- Livelock is deadlock's embarrassed cousin: everyone retries politely and in sync forever (two people side-stepping in a hallway). Fix: randomized backoff — jitter is a correctness tool, not just a networking nicety.
- Distributed deadlock: same theory, no shared memory to inspect — hence lock managers with timeouts (a lease is 'preemption by clock'), and why every distributed lock has a TTL.