Starvation

⭐ Interview Importance: MEDIUM
⏱️ Revision Time: 5 min

TL;DR

  • Starvation occurs when a thread is perpetually denied access to the CPU or a required lock, preventing it from making any progress.
  • Unlike a deadlock, the system as a whole hasn’t frozen, but one or more specific threads are effectively stuck.
  • Often caused by unfair locks, thread priority abuse, or threads holding locks for too long.

Concept

If a parent distributes cookies to a group of children, and always gives cookies to the tallest children first, the shortest child might never get a cookie if the taller children keep coming back. The shortest child is “starving”.

In Java, if Thread A is constantly acquiring a lock, releasing it, and immediately acquiring it again, a slower Thread B might be stuck in the BLOCKED state forever. Thread B is starving.

Another common cause is setting Thread Priorities. If you have 10 threads with MAX_PRIORITY constantly doing heavy calculations, and 1 thread with MIN_PRIORITY, the OS scheduler might never assign CPU time to the low-priority thread.

Examples

public class StarvationExample {
    public static void main(String[] args) {
        // Shared lock
        Object lock = new Object();
        
        // This greedy thread takes the lock and rarely lets it go
        Thread greedyThread = new Thread(() -> {
            while (true) {
                synchronized (lock) {
                    System.out.println("Greedy thread working...");
                    try { Thread.sleep(100); } catch (Exception e) {}
                }
            }
        });
        
        // This starving thread will rarely, if ever, get a chance to run
        Thread starvingThread = new Thread(() -> {
            while (true) {
                synchronized (lock) {
                    System.out.println("Starving thread finally got the lock!");
                }
            }
        });
        
        greedyThread.setPriority(Thread.MAX_PRIORITY);
        starvingThread.setPriority(Thread.MIN_PRIORITY);
        
        starvingThread.start();
        greedyThread.start();
    }
}

Interview Questions

Q: How do you prevent thread starvation?
A: 1. Use Fair Locks: Instead of synchronized, use new ReentrantLock(true). A fair lock guarantees that the thread waiting the longest gets the lock next, establishing a strict queue.
2. Avoid Thread Priorities: Do not mess with Thread.setPriority(). Let the OS manage standard time-slicing.
3. Minimize Critical Sections: Ensure threads hold locks for the absolute minimum amount of time necessary. Don’t do heavy I/O operations (like downloading files) while holding a lock.