C Mastery / Deadlock, Livelock, Starvation, Priority Inversion
Part 10 — Concurrency

Deadlock, Livelock, Starvation, Priority Inversion

This chapter covers the four classic concurrency pathologies: deadlock, livelock, starvation, and priority inversion.

Why This Matters

These are the failure modes that make concurrent code "hang," "spin forever," "never get a turn," or "block a high-priority task." Recognizing and preventing them is essential for building reliable concurrent systems.

Prerequisites

Core Concept

Deadlock

Two or more threads each hold a lock and wait for a lock held by another, forming a cycle. All are permanently stuck.

Thread A: lock X, then lock Y
Thread B: lock Y, then lock X

Livelock

Threads repeatedly change state in response to each other but make no progress (they are "busy" but stuck), often in a spin/retry loop.

Starvation

A thread never gets the resources it needs because others always win (e.g., a readers-preferred rwlock starving writers).

Priority inversion

A low-priority thread holds a lock needed by a high-priority thread, and a medium-priority thread preempts the low-priority holder, so the high-priority thread waits behind the medium one. This famously caused the Mars Pathfinder bug.

Examples

Deadlock

mtx_lock(&a);
mtx_lock(&b);   /* B */
/* ... */
mtx_unlock(&b);
mtx_unlock(&a);

/* other thread */
mtx_lock(&b);
mtx_lock(&a);   /* A */
/* ... */

If both threads acquire their first lock, each blocks forever on the second.

Priority inversion (embedded/RTOS)

A low-priority task holds a mutex; a high-priority task blocks on it; a medium-priority task (which does not need the mutex) runs, delaying the low task and therefore the high task.

How It Works

Deadlock is a cyclic wait graph. Livelock is a cycle of reactions. Starvation is a fairness failure. Priority inversion is an interaction between locking and scheduling priorities.

Variations

Deadlock prevention strategies

lock.

Priority inheritance

An RTOS can temporarily raise the low-priority holder's priority to that of the high-priority waiter, breaking priority inversion.

Common Mistakes

Undefined Behavior

shared state is UB.

Portability

scheduling (c.rtos.priority-inversion).

Under the Hood

The OS scheduler and lock implementation determine the exact behavior. Tools like helgrind/TSan can detect deadlocks/races.

Practical Usage

Exercises

1. Write a two-thread deadlock and observe the hang. 2. Fix it with consistent lock ordering. 3. Write a livelock (two threads retrying) and fix it with backoff. 4. Explain priority inversion and priority inheritance.

Deep Challenge

Implement a deadlock detector that tracks lock acquisitions and detects cycles in the wait-for graph. Explain its overhead and limitations.

References

priority-inheritance literature.

Verification

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.conc.deadlock06
c.conc.livelock06
c.conc.starvation05
c.conc.priority-inversion06