DEV Community

Cover image for Why Systems Freeze Forever: The 4 Deadlock Conditions Explained with Code
Binary Dose
Binary Dose

Posted on Originally published at binarydose.in

Why Systems Freeze Forever: The 4 Deadlock Conditions Explained with Code

Why Systems Freeze Forever: The 4 Deadlock Conditions Explained with Code

A deadlock is not slow code or an infinite loop. It is an eternal system freeze where two or more threads sleep forever, each holding a lock the other needs.

In 1971, computer scientist Edward G. Coffman Jr. proved that a deadlock is mathematically impossible unless 4 hardware conditions hold simultaneously.


⚡ The 4 Coffman Conditions

Thread 1 holds [Lock A] ──waits for──> [Lock B]
     ▲                                       │
     │                                       ▼
[Lock A] <──waits for── Thread 2 holds [Lock B]
Enter fullscreen mode Exit fullscreen mode
  1. Mutual Exclusion: Resources are non-shareable. Only one thread can hold an exclusive mutex or write lock at a time.
  2. Hold and Wait: A thread holding Resource A is permitted to block while waiting to acquire Resource B.
  3. No Preemption: The operating system kernel cannot forcibly seize an allocated lock. It must be released voluntarily.
  4. Circular Wait: A closed dependency loop exists where Thread 1 waits for Thread 2, and Thread 2 waits for Thread 1.

💻 The Classic Deadlock Trap in C

Here is the quintessential anti-pattern that freezes production services:

// Thread 1
void* thread_one(void* arg) {
    pthread_mutex_lock(&lock_A);
    sleep(1); // Simulating work...
    pthread_mutex_lock(&lock_B); // Stalls waiting for Thread 2!

    // Critical Section
    pthread_mutex_unlock(&lock_B);
    pthread_mutex_unlock(&lock_A);
    return NULL;
}

// Thread 2
void* thread_two(void* arg) {
    pthread_mutex_lock(&lock_B);
    sleep(1);
    pthread_mutex_lock(&lock_A); // Stalls waiting for Thread 1!

    // Critical Section
    pthread_mutex_unlock(&lock_A);
    pthread_mutex_unlock(&lock_B);
    return NULL;
}
Enter fullscreen mode Exit fullscreen mode

🛠️ The Mathematical Law of Prevention

Because all 4 conditions must hold simultaneously for a deadlock to exist:

If you break even ONE condition, deadlock becomes mathematically impossible!

The most practical production strategy is breaking Circular Wait via Strict Lock Hierarchy Ordering:

// Enforce global acquisition order: Always Lock A before Lock B!
void* safe_worker(void* arg) {
    pthread_mutex_lock(&lock_A);
    pthread_mutex_lock(&lock_B);
    // Safe: Circular wait can never form!
    pthread_mutex_unlock(&lock_B);
    pthread_mutex_unlock(&lock_A);
    return NULL;
}
Enter fullscreen mode Exit fullscreen mode

🚀 Test and Visualize Deadlocks Interactively

Static diagrams only tell half the story. You can build Resource Allocation Graphs (RAG) and simulate cycle detection algorithms interactively on Binary Dose.

Top comments (0)