javaconcurrencystarvation

Thread priorities no effect


I'm writing a starvation simulation in Java. However, when I run it, it simply doesn't work almost any time. I'm working on MacOS. The code is like:

public class StarvationNew {
private static SharedObject sharedObject = new SharedObject(); // to jest ten obiekt (operacja) na ktorym sie blokuje
private static volatile boolean isActive = true;

public static void main(String[] args) {
    Thread t1 = new Thread(new Worker(), "Thread_1");
    Thread t2 = new Thread(new Worker(), "Thread_2");
    Thread t3 = new Thread(new Worker(), "Thread_3");

    t1.setPriority(Thread.MAX_PRIORITY);
    t2.setPriority(Thread.MAX_PRIORITY);
    t3.setPriority(Thread.MIN_PRIORITY);

    t1.start();
    t2.start();
    t3.start();


    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    isActive = false;

}

private static class Worker implements Runnable {
    private int runCount = 0;

    @Override
    public void run() {
        while(isActive) {
            sharedObject.playOperation();
            runCount++;
        }
        System.out.println("--------");
        System.out.println(Thread.currentThread().getName() + " ended with: " + runCount);
        System.out.println("--------");
    }
}

}

and the SharedObject just simulates long running operations looks like this:

public class SharedObject {
    public synchronized void playOperation() {
        try {
            // long operations
            System.out.println(Thread.currentThread().getName());
            Thread.sleep(150);
        } catch(InterruptedException e) {
            e.printStackTrace();
        }
    }
}

I wonder what is the mistake in this code.


Solution

  • There are several things to keep in mind when working with Java threads.

    1. The rules for thread priorities are highly system-dependent. When the virtual machine relies on the thread implementation of the host platform, the thread scheduling is at the mercy of that thread implementation.
    2. Rule of thumb: At any given time, the highest priority thread is running. However, this is not guaranteed. The thread scheduler may choose to run a lower priority thread to avoid starvation. For this reason, use thread priority only to affect scheduling policy for efficiency purposes. Do not rely on it for algorithm correctness.
    3. What happens if there is more than one runnable thread with the same (highest) priority? One of the highest priority threads gets picked. It is completely up to the thread scheduler how to arbitrate between threads of the same priority. The Java programming language gives no guarantee that all of the threads get treated fairly.

    The above being said, I don't see anything abnormal with the following output on my Windows 10 (Java 8) machine:

    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_1
    Thread_3
    --------
    Thread_1 ended with: 34
    --------
    --------
    Thread_2
    Thread_3 ended with: 1
    --------
    --------
    Thread_2 ended with: 1
    --------
    

    Have a look at this for further details.