What is a 'liveness failure' in concurrent programming, and how do deadlock, livelock, and starvation differ?
answer
- Liveness = forward progress; failure = no progress, no crash
- Deadlock = stuck + idle (cycle)
- Livelock = stuck + busy (mutual reaction/retry)
- Starvation = runnable but never gets its turn (unfairness)
- Two axes: blocked vs running, and cycle vs reaction vs unfairness
basics
~20 sA liveness failure means threads never make progress. Deadlock: threads are blocked forever waiting on each other. Livelock: threads keep changing state reacting to each other but get nothing done. Starvation: one thread is perpetually denied a resource it needs.
solid answer
~50 sLiveness is the property that a program eventually does something useful; a liveness failure is when it stops making progress even though it isn't crashing. There are three classic kinds. Deadlock: two or more threads are each blocked waiting for a lock the other holds, so all are stuck and idle. Livelock: threads are not blocked — they actively run and change state in response to one another — but their combined behavior keeps them looping without progress (like two people repeatedly stepping aside in a hallway). Starvation: a thread is runnable but is perpetually denied the CPU or a lock it needs, usually because others keep winning, e.g. unfair scheduling or thread priorities. The key contrast: deadlock threads are stuck and idle; livelock threads are stuck but busy; a starved thread could run but never gets its turn.
go deeper
Can state the one-line definition of each: deadlock = blocked forever in a cycle, livelock = busy but no progress, starvation = never gets its turn.
Distinguishes them on the two axes (blocked vs running; cycle vs reaction vs unfairness) and gives a concrete code or hallway example for each.
Explains how a naive deadlock fix produces livelock, connects starvation to scheduling/priority and fairness, and reasons about CPU-usage symptoms when diagnosing.
Frames liveness vs safety as formal program properties, discusses detectability/tooling, and weighs design choices (fair locks, randomized backoff, bounded retries) against throughput across a system.
## What 'liveness' means In concurrency, properties of a program are split into two families. A **safety** property says 'nothing bad ever happens' (e.g. no two threads corrupt the same data). A **liveness** property says 'something good eventually happens' — the program keeps making forward progress and completes its work. A **liveness failure** is therefore a bug where the program does not crash and does not corrupt data, but **stops making progress**. These are dangerous precisely because nothing looks broken: no exception, no crash, just a hang or a thread that never finishes. A **thread** is an independent path of execution. A **lock** (or **mutex**) is a token only one thread can hold at a time, used to protect shared data; a thread that wants a held lock must **block** (wait, doing nothing) until it is released. The **scheduler** is the part of the OS/JVM that decides which runnable thread gets a CPU core next. There are three classic liveness failures: ### 1. Deadlock Two or more threads each hold a lock and each wait for a lock the other holds, forming a cycle of waiting that never breaks. Example: Thread A holds lock 1 and wants lock 2; Thread B holds lock 2 and wants lock 1. Neither can proceed, neither will release, so both are **blocked forever and idle** (using no CPU). This is the most famous liveness failure. ### 2. Livelock Threads are **not blocked** — they keep running and **actively change their state in response to each other**, but the system as a whole makes **no progress**. The classic image: two people meet in a narrow hallway; each politely steps to the same side to let the other pass, then both step back, then both step the same way again — forever. In code, this often arises from a too-clever deadlock 'fix': a thread that can't get all the locks it needs releases what it holds, backs off, and retries — but if all contending threads do the same thing in lockstep, they keep releasing and retrying in sync and none ever acquires everything. Unlike deadlock, livelocked threads burn CPU. ### 3. Starvation A single thread is **perpetually denied a resource it needs** — CPU time or a lock — even though it is ready to run. It isn't waiting in a cycle (not deadlock) and isn't reacting to others (not livelock); it simply never wins. Common causes: **unfair scheduling** (the resource is repeatedly handed to other threads), **thread priorities** (low-priority threads can be starved by a steady stream of high-priority ones on some platforms), or a greedy thread that holds a shared resource for very long stretches. The starved thread could make progress if it ever got its turn — but it never does. ### The contrast table | | Threads are… | CPU usage | Cause | |---|---|---|---| | Deadlock | blocked, idle | none | circular lock-wait | | Livelock | running, busy | high | symmetric reaction/retry | | Starvation | runnable, denied | low for the victim | unfair allocation / priority | ### How to derive your answer Start from 'liveness = forward progress.' Then for each failure ask two questions: *Is the stuck thread blocked or running?* and *Is it stuck because of a cycle, mutual reaction, or simple unfairness?* Deadlock = blocked + cycle; livelock = running + mutual reaction; starvation = runnable but denied + unfairness. That two-axis mental model lets you classify any liveness bug you meet.
- Which of the three failures consumes CPU while stuck, and why?Livelock. The threads are not blocked — they keep executing and changing state in response to each other, so they actively spin. Deadlocked threads are blocked and idle; a starved thread simply doesn't get scheduled.
- Can starvation occur without any locks at all?Yes. Pure CPU starvation needs no locks — a runnable low-priority thread can be perpetually passed over by the scheduler in favor of busy higher-priority threads.
saying these in an interview costs you the question
- Saying livelock is just deadlock — livelocked threads are actively running, not blocked
- Claiming all three pin the CPU — only livelock typically burns CPU; deadlock is idle
- Treating starvation as a cycle of waiting; it's about being perpetually denied, not a mutual wait
- Confusing a liveness failure with a crash or data corruption (those are safety/availability issues)