DeadlocksDeadlock Conditions & PreventionHard⏱️ ~2 min

Breaking Hold-and-Wait

Alternative Strategy
Breaking hold-and-wait means threads cannot hold resources while waiting for more. Either get everything at once, or hold nothing.

Approach 1: All-or-Nothing

Request all needed locks atomically. If any lock is unavailable, release all and retry. No thread ever holds some locks while waiting for others.

Approach 2: Two-Phase Locking

Phase 1: Acquire all locks (growing phase). Phase 2: Release all locks (shrinking phase). Once you start releasing, you cannot acquire more. Used in databases.

All-or-Nothing Pattern
Try Acquire AlltryLock(A)tryLock(B)tryLock(C)All succeeded?Proceed!Any failed?Release all, retry

The Drawbacks

Reduced concurrency: Holding all locks longer than needed. Others wait even if they need only one.

Starvation risk: Thread keeps failing to get all locks, retries forever while others succeed.

Must know all locks upfront: Sometimes you do not know what you need until partway through.

When to Use: Works well when lock sets are small and known in advance. Impractical for dynamic or large lock sets. Lock ordering is usually preferred.
💡 Key Takeaways
All-or-nothing: acquire all locks atomically, or none. Release and retry if any unavailable.
Two-phase locking: growing phase (acquire), then shrinking phase (release). No mixing.
Eliminates hold-and-wait: thread never holds a lock while waiting for another.
Drawback: reduced concurrency, holding locks longer than needed. Possible starvation.
Requires knowing all locks upfront. Not always practical for dynamic scenarios.
📌 Examples
1All-or-nothing: tryLock(A), tryLock(B). If B fails, unlock(A), sleep, retry both.
2Database 2PL: transaction acquires row locks during query, releases all at commit. Strict ordering.
3Resource allocator: request (CPU, memory, disk) as a batch. If any unavailable, wait without holding others.
← Back to Deadlock Conditions & Prevention Overview