Programming Fundamentals › Concurrency & Async
Starvation
A task never gets the resources it needs to run.
Also known as: starvation, resource starvation, thread starvation
Starvation is when a task can never get the resources it needs to run, even though the system as a whole keeps making progress. It’s not stuck (like a deadlock) and it’s not busy-spinning (like a livelock); it’s simply never chosen. Other work is always served first, and this task waits indefinitely.
high-priority work arrives continuously → low-priority task never runs
lock handed repeatedly to a fast thread → slow thread never acquires it
Typical causes:
- Unbounded priority. Strict priority scheduling lets a stream of high-priority tasks starve everything below them. The higher class must have a limit or a share of time.
- Unfair locks. A lock that doesn’t queue fairly can let one thread repeatedly re-acquire it while others wait forever.
- Long-held resources. One task holding a shared resource for a very long time blocks everyone behind it.
- Resource quotas. A pool of connections consumed by heavy users can leave a small user permanently waiting.
The classic mistakes:
- Confusing it with deadlock or livelock. Three different shapes: deadlock = blocked and idle; livelock = busy but no progress; starvation = progress overall, but this task never gets its turn. The remedy differs for each.
- Assuming lower priority means “eventually”. Under strict priority, “eventually” can be “never”. If a task must run, it needs a guaranteed share, not just a lower class.
- Trusting locks to be fair. Many mutexes aren’t fair by design, because fairness costs throughput. If a task must make progress, add fairness or timeouts.
- Fixing it with more resources. More capacity can ease contention but doesn’t solve unfairness — the same task can still be passed over.
Fixes target fairness: bound the high-priority class, use fair/queued locks, add aging (gradually raise a waiting task’s priority), or give each task a guaranteed slice. It shows up plainly in scheduling and process priority, and in any queue where a few producers can monopolise a shared pool. The goal is progress for every task, not just the system overall.