Saturday, March 30, 2019

Thread Starvation in Java Multi-Threading

In any multi-threaded application, where you have multiple threads vying for the access over the shared resources you may come across a situation where a thread (or a bunch of threads) is unable to gain regular access to shared resources and is unable to make progress. This situation is known as thread starvation.

Thread starvation in multi-threading may happen because other “greedy” threads are gaining the lock and access to the shared resource, resulting in a thread (or a bunch of threads) getting starved of access to shared resources and CPU time.

Thread starvation in Java

Some of the reasons why thread starvation may happen in Java-

  • If there is an object providing a synchronized method that requires a lots of processing time. If there is a thread invoking this method quite frequently, other threads that also need to access the synchronized method will be blocked.
  • If there are some higher priority threads those threads will get executed first rather than the threads having lower priority.
  • If you are using wait-notify signalling, then theoretically a thread that is waiting to get access to a shared resource may wait indefinitely if always some other thread is notified and get access to the shared resource.

Thread starvation scenario - Java Example

Let’s see an example in Java where thread starvation scenario is shown.

Here we have a class called ThreadStarveDemo which has a synchronized method displayValues(). Three threads are created which will share an object of class ThreadStarveDemo. There are two classes Display and Display1.

Two thread objects are created of type Display and one thread object of type Display1 is created. While the two thread objects of type Display are given the maximum priority the thread object of type Display1 is given the minimum priority.

In displayValues() method, sleep method of thread class is used to simulate some delay (processing time) and it is called thrice from maximum priority threads to have a scenario that the method is invoked frequently from thread.

class Display implements Runnable{
    private ThreadStarveDemo td;
    Display(ThreadStarveDemo td){
        this.td = td;
    }
    @Override
    public void run() {
        td.displayValues();
        System.out.println("Calling again");
        td.displayValues();
        System.out.println("Calling again");
        td.displayValues();
        //System.out.println("Calling again");       
    }    
}

/**
 * 
 */
class Display1 implements Runnable{
    private ThreadStarveDemo td;
    Display1(ThreadStarveDemo td){
        this.td = td;
    }
    @Override
    public void run() {
        try {
            // introducing some delay
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        td.displayValues();
        //System.out.println("Calling again");       
    }    
}

public class ThreadStarveDemo {
    
    synchronized void displayValues(){
        System.out.println("In ThreadStarveDemo For thread " + 
             Thread.currentThread().getName());
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("For thread " + Thread.currentThread().getName());
        for(int i = 0; i < 3; i++){
            System.out.println("Value of i " + i);
        }        
    }
    
     public static void main(String[] args) {
         ThreadStarveDemo td1 = new ThreadStarveDemo();
         // Creating 3 threads
         Thread thread0 = new Thread(new Display1(td1));
         Thread thread1 = new Thread(new Display(td1));
         Thread thread2 = new Thread(new Display(td1));
        
         // Setting priorities
         thread1.setPriority(Thread.MAX_PRIORITY);
         thread2.setPriority(Thread.MAX_PRIORITY);
         thread0.setPriority(Thread.MIN_PRIORITY);
          
         thread0.start();
         thread1.start();
         thread2.start();
        
     }
}

Output

In ThreadStarveDemo For thread Thread-2
For thread Thread-2
Value of i 0
Value of i 1
Value of i 2
In ThreadStarveDemo For thread Thread-1
Calling again
For thread Thread-1
Value of i 0
Value of i 1
Value of i 2
Calling again
In ThreadStarveDemo For thread Thread-2
For thread Thread-2
Value of i 0
Value of i 1
Value of i 2
Calling again
In ThreadStarveDemo For thread Thread-1
For thread Thread-1
Value of i 0
Value of i 1
Value of i 2
Calling again
In ThreadStarveDemo For thread Thread-2
For thread Thread-2
Value of i 0
Value of i 1
Value of i 2
In ThreadStarveDemo For thread Thread-0
For thread Thread-0
Value of i 0
Value of i 1
Value of i 2
In ThreadStarveDemo For thread Thread-1
For thread Thread-1
Value of i 0
Value of i 1
Value of i 2

Here it can be seen that Thread-0 has to invoke displayValues() method only once but that invocation is delayed by the threads of maximum priority.

Think of same scenario in a multi-threaded application having lots of threads and a synchronized method called from various points in the application. There is a very good chance that thread starvation may happen.

That's all for this topic Thread Starvation in Java Multi-Threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Race condition in Java multi-threading
  2. Deadlock in Java multi-threading
  3. Volatile in Java
  4. String and thread-safety in Java
  5. Java Multi-threading interview questions

You may also like-

  1. Lock Striping in Java Concurrency
  2. Non-blocking algorithms
  3. AtomicInteger in Java Concurrency
  4. Executor and ExecutorService in Java concurrency
  5. Wiring collections in Spring
  6. Insert\Update using NamedParameterJDBCTemplate in Spring framework
  7. How to create immutable class in Java
  8. static block in Java