You are here: Home / Topics / What are Deadlocks: When Safety Itself Freezes the System

What are Deadlocks: When Safety Itself Freezes the System

Filed under: Solid System Design on 2026-01-02 13:30:29

Deadlocks: When Safety Itself Freezes the System

“Deadlocks happen not because code is unsafe, but because it is too safe in the wrong order.”

Yesterday you learned how to lock correctly.
Today you learn what happens when locks fight each other.

1️⃣ What Is a Deadlock (Plain English)

A deadlock happens when:

  • Two or more transactions hold locks
  • Each is waiting for the other to release a lock
  • None can proceed

➡️ System freezes, not crashes.

2️⃣ The Classic Deadlock Example (Bank Transfer)

Two accounts:

A, B

Two concurrent transfers:

Transaction T1

LOCK A
LOCK B (waits)

Transaction T2

LOCK B
LOCK A (waits)

? Both wait forever → deadlock

3️⃣ Why Deadlocks Appear Only in Production

  • More concurrency
  • More transactions
  • Longer transactions
  • Slower DB responses

Development rarely creates the timing needed.

4️⃣ Conditions Required for Deadlock (MEMORIZE)

All four must exist:

1️⃣ Mutual exclusion (locks)
2️⃣ Hold and wait
3️⃣ No preemption (can’t force release)
4️⃣ Circular wait

Remove any one → no deadlock.

5️⃣ How Databases Handle Deadlocks

Good news:

Databases detect deadlocks automatically

What happens:

  • DB picks a victim transaction
  • Rolls it back
  • Other transaction proceeds

Bad news:

  • If your code isn’t retry-safe → user sees error

6️⃣ The #1 Rule to Avoid Deadlocks (MOST IMPORTANT)

Always acquire locks in the SAME ORDER

❌ Bad

A → B
B → A

✅ Good

A → B
A → B

In code:

if (fromId < toId) {
    lock(from);
    lock(to);
} else {
    lock(to);
    lock(from);
}

7️⃣ Keep Transactions SHORT

Long transactions:

  • Hold locks longer
  • Increase deadlock chance

❌ Bad

@Transactional
public void process() {
    lock();
    callExternalAPI(); // ?
    update();
}

✅ Good

callExternalAPI();
@Transactional
public void process() {
    lock();
    update();
}

8️⃣ Atomic Updates Reduce Deadlocks

This:

UPDATE account
SET balance = balance - 100
WHERE id = 1 AND balance >= 100;

Is deadlock-free
(no read lock + write lock sequence)

9️⃣ Retry Strategy (IMPORTANT)

Deadlocks are expected.

Safe retry:

  • Short delay
  • Limited retries
  • Only for idempotent operations
@Retryable(
  value = DeadlockLoserDataAccessException.class,
  maxAttempts = 3
)

? What NOT to Do ❌

MistakeWhy
Ignore deadlock errorsUsers see failures
Long transactionsLock explosion
Random lock orderGuaranteed deadlocks
Retrying non-idempotent opsData corruption

? Mental Checklist (Before Writing Transactional Code)

Ask:

  1. What rows will I lock?
  2. In what order?
  3. How long will I hold them?
  4. What happens if DB kills my transaction?

If you can’t answer → redesign.

? One-Sentence Rule

Deadlocks are a sign of correct locking without correct ordering.

? Day 5 Preview

Isolation Levels — How Much Reality Your Transaction Sees

You’ll learn:

  • READ COMMITTED vs SERIALIZABLE
  • Phantom reads
  • Why higher isolation ≠ always better

About Author:
N
Neha Sharma     View Profile
Hi, I am using MCQ Buddy. I love to share content on this website.