Deadlock, Livelock & Starvation
debt(d7/e5/b5/t7)
Closest to 'only careful code review or runtime testing' (d7). The term's detection_hints explicitly state automated=no, and tools listed (mysql-innodb-monitor, datadog) are runtime monitoring tools that detect deadlocks after they occur, not prevent them at code time. Deadlocks manifest as silent hangs in production requiring process restarts.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix mentions 'always acquiring locks in a consistent alphabetical/dependency order' which requires auditing all code paths that acquire locks and ensuring consistent ordering — this spans multiple functions/classes but typically within the data-access layer, not architectural rework.
Closest to 'persistent productivity tax' (b5). Applies to web, cli, and queue-worker contexts, meaning any part of the system doing concurrent database or resource access must consider lock ordering. Every future feature touching shared resources must follow the locking discipline, creating ongoing overhead for multiple work streams.
Closest to 'serious trap - contradicts how similar concept works elsewhere' (t7). The misconception field explicitly states developers confuse deadlock and livelock as the same thing. Common mistakes show devs intuitively retry failed locks without backoff (creating livelock) or don't realise different code paths acquiring locks in different orders guarantees eventual deadlock — these are non-obvious behaviours that contradict the 'just retry it' instinct.
Also Known As
TL;DR
Explanation
Deadlock requires four conditions (Coffman conditions): mutual exclusion, hold and wait, no preemption, circular wait. Prevention: break any one condition — typically consistent lock ordering. Livelock: processes respond to each other but make no progress (e.g. two people stepping the same way in a corridor). Starvation: low-priority processes never get scheduled — prevent with fair scheduling or priority aging. Database deadlocks are automatically detected and one transaction is rolled back.
Diagram
sequenceDiagram
participant T1 as Thread 1
participant T2 as Thread 2
Note over T1,T2: Deadlock
T1->>T1: Lock resource A
T2->>T2: Lock resource B
T1->>T1: Wait for B - blocked
T2->>T2: Wait for A - blocked
Note over T1,T2: Both wait forever
Note over T1,T2: Livelock
T1->>T1: Acquire A, detect conflict
T1->>T1: Release A, retry
T2->>T2: Acquire A, detect conflict
T2->>T2: Release A, retry
Note over T1,T2: Both keep retrying - no progress
Common Misconception
Why It Matters
Common Mistakes
- Acquiring locks in different orders in different code paths — guaranteed eventual deadlock.
- Not setting lock timeouts — a deadlock with infinite timeout hangs the process forever.
- Retrying a locked resource with no backoff — creates livelock where both processes keep retrying simultaneously.
- Holding a lock while doing slow I/O — extends the deadlock window unnecessarily.
Code Examples
// Inconsistent lock order — deadlock risk:
// Thread 1: Thread 2:
lock('account:1'); lock('account:2');
lock('account:2'); lock('account:1'); // Both block — deadlock!
debit(1, 100); debit(2, 100);
credit(2, 100); credit(1, 100);
unlock('account:2'); unlock('account:1');
unlock('account:1'); unlock('account:2');
// Consistent lock order — no deadlock possible:
function transfer(int $from, int $to, float $amount): void {
// Always lock lower ID first — consistent ordering prevents deadlock:
$first = min($from, $to);
$second = max($from, $to);
$lock1 = acquireLock("account:$first", timeout: 5);
$lock2 = acquireLock("account:$second", timeout: 5);
// ... debit/credit ...
releaseLock($lock2);
releaseLock($lock1);
}