Home/Learn/Operating Systems/Priority Scheduling & Starvation

Priority Scheduling & Starvation

Intermediate
CPU Scheduling

Priority scheduling assigns each process a priority and always runs the highest-priority process next, but risks starvation of low-priority processes — solved by aging.

Overview

In priority scheduling, each process is assigned a numeric priority. The CPU is allocated to the process with the highest priority (lowest number in most OS conventions). Priority scheduling can be preemptive (a new high-priority arrival preempts the running process) or non-preemptive (current process runs to completion). Static priorities are assigned once and never change. Dynamic priorities change over time. The critical problem is starvation (indefinite postponement): a continuous stream of high-priority processes can prevent low-priority ones from ever running. The classic solution is aging: gradually increasing the priority of processes that have been waiting a long time. Priority inversion is a famous bug: a high-priority task is blocked waiting for a resource held by a low-priority task. The Mars Pathfinder mission experienced this in 1997, solved by priority inheritance.

Starvation and Aging

Starvation is the indefinite postponement of low-priority processes. It is like a hospital triage system where critical patients always go first — a stable patient admitted on Monday may still be waiting on Friday if critical cases keep arriving. Aging solves this by incrementally boosting the priority of waiting processes. After waiting T time units, a process's effective priority increases, eventually becoming high enough to run.

Java — priority scheduling with aging to prevent starvation
// Priority scheduling with aging to prevent starvation
// Lower number = higher priority (convention)

class Process {
    int id, basePriority, effectivePriority, waitingTime;
    Process(int id, int priority) {
        this.id = id;
        this.basePriority = priority;
        this.effectivePriority = priority;
        this.waitingTime = 0;
    }
}

List<Process> readyQueue = new ArrayList<>();
readyQueue.add(new Process(1, 1));   // high priority
readyQueue.add(new Process(2, 10));  // low priority — risk of starvation
readyQueue.add(new Process(3, 5));   // medium priority

int AGING_INTERVAL = 3;   // boost priority every 3 time units
int agingBoost = 1;       // increase effective priority by 1 per interval

// Simulate aging: every tick, boost waiting processes' effective priority
for (int tick = 0; tick < 15; tick++) {
    for (Process p : readyQueue) {
        p.waitingTime++;
        if (p.waitingTime % AGING_INTERVAL == 0) {
            p.effectivePriority = Math.max(1,
                p.effectivePriority - agingBoost);  // lower number = higher priority
            System.out.printf("Tick %2d: P%d priority boosted to %d%n",
                tick, p.id, p.effectivePriority);
        }
    }
}
// Eventually, low-priority P2 (base=10) ages up to compete with high-priority tasks

Java Thread Priority and Priority Inversion

Java provides Thread.setPriority(int) with values 1 (MIN_PRIORITY) to 10 (MAX_PRIORITY), default 5 (NORM_PRIORITY). However, the mapping to OS priorities is JVM and OS dependent — on Linux, Java thread priorities may be ignored entirely. The correct way to achieve priority-based behavior in Java is via explicit scheduling with PriorityBlockingQueue or ReentrantLock(fair=true). Priority inversion occurs when a high-priority thread is blocked on a resource held by a low-priority thread, while a medium-priority thread runs instead — the Mars Pathfinder bug.

Java — Thread.setPriority() caveat + PriorityBlockingQueue for reliable priority
// Java Thread priorities — advisory only, OS-dependent
Thread high = new Thread(() -> System.out.println("High priority task"));
high.setPriority(Thread.MAX_PRIORITY);   // 10

Thread low = new Thread(() -> System.out.println("Low priority task"));
low.setPriority(Thread.MIN_PRIORITY);    // 1

// WARNING: On Linux with default JVM settings, these priorities are often ignored
// Use explicit prioritization with PriorityBlockingQueue for reliable behavior

// Priority-aware task queue — reliably prioritized
PriorityBlockingQueue<Runnable> priorityQueue = new PriorityBlockingQueue<>(
    10, Comparator.comparingInt(r -> ((PrioritizedTask) r).priority)
);

record PrioritizedTask(int priority, Runnable work) implements Runnable, Comparable<PrioritizedTask> {
    public void run() { work.run(); }
    public int compareTo(PrioritizedTask other) {
        return Integer.compare(this.priority, other.priority); // lower = higher priority
    }
}

priorityQueue.add(new PrioritizedTask(5, () -> System.out.println("Medium task")));
priorityQueue.add(new PrioritizedTask(1, () -> System.out.println("Critical task")));
priorityQueue.add(new PrioritizedTask(9, () -> System.out.println("Low task")));

// Drain in priority order
while (!priorityQueue.isEmpty()) priorityQueue.poll().run();
// Output: Critical → Medium → Low

Key Points to Remember

  • 1Priority scheduling always runs the highest-priority ready process; can be preemptive or non-preemptive.
  • 2Starvation: low-priority processes may never run if high-priority tasks continuously arrive.
  • 3Aging: gradually increase the effective priority of waiting processes to prevent starvation.
  • 4Priority inversion: high-priority task blocked by low-priority task holding a shared resource.
  • 5Priority inheritance protocol: low-priority task inherits the high priority of whoever is waiting on it.
  • 6Java Thread.setPriority() is advisory — OS mapping is JVM and platform dependent.

Interview Questions

Sign in to ask Aria
1

What is priority inversion and how does priority inheritance solve it?

HardGoogle
2

What is starvation in scheduling and how does aging prevent it?

MediumAmazon
3

Why is Thread.setPriority() unreliable on Linux JVMs?

MediumAtlassian
4

Describe the Mars Pathfinder priority inversion bug.

HardMicrosoft

Ask Aria about Priority Scheduling & Starvation

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…