JDK-6316090 : 5.0 "synchronized" method causes starvation
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 5.0u2
  • Priority: P2
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_2.5.1
  • CPU: x86
  • Submitted: 2005-08-25
  • Updated: 2010-08-19
  • Resolved: 2005-08-30
Related Reports
Duplicate :  
Relates :  
Relates :  
Description
In 5.0, if using "synchronized" feature, scheduling algorithm will favor new threads, starving others in the process. This behavior is total different than in 1.4. This causes problems in some of our system since some threads never got served and starved.

Tested on 1.5.0_05-b03 and 1.5.0_02-b09.

Following is the simple program that will print out which threads got served first. Compile with 1.4 and 5.0 to see the difference.

Source code (TestThreading.java):
#####################################################################
public class TestThreading {
    
    public static void main(String[] args) throws Exception {
        Thread threads[]  = new Thread[100];
        int    stats[]    = new int[100];

        Thread stat_thread= new Thread(new Stat(stats));
        stat_thread.start();

        for (int i = 0; i < 100; i++) {
            threads[i] = new Thread(new Driver(i, stats));
            threads[i].start();
        }

        for (int i = 0; i < 100; i++) {
            threads[i].join();
        }
        stat_thread.interrupt();
    }

    public static class Stat implements Runnable {
        private int[] stats;

        public Stat(int[] stats) {
            this.stats = stats;
        }
        
        public void run() {
            try{
                while (true) {
                    Thread.sleep(20000);
                    printTopThreads(10);
                }
            }
            catch(Exception e){
              
            }
        }

        private void printTopThreads(int rank) {
            int[] temp = new int[100];
            System.arraycopy(stats, 0, temp, 0, 100);

            int max = 0;
            int idx = 0;

            for(int i=0; i<rank; i++) {
                max = 0;
                for(int j=99; j>=0; j--) {
                    if(temp[j] >= max) {
                        max = temp[j];
                        idx = j;
                    }
                }
                System.out.print("[");
                if(idx <10)
                    System.out.print(" ");
                System.out.println( idx + "] - " + max);
                temp[idx] = -1;
            }
            System.out.println("**********************************************");
        }
    }
                 
    
    public static class Driver implements Runnable {
        private int id;
        private int[] stats;
        
        public Driver(int id, int[] stats) {
            this.id = id;
            this.stats = stats;
        }
        
        public void run() {

            BottleNeck b = BottleNeck.getInstance();
            for(int i = 0; i < 50; i++) {
                b.doSomething(id);
                stats[id] ++;
                try {
                    Thread.sleep(25);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
    
    public static class BottleNeck {
        private static BottleNeck instance = new BottleNeck();
        
        public static BottleNeck getInstance() {
            return instance;
        }
        
        public synchronized void doSomething(int id) {
            try {
                //System.out.println("Thread " + id);
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}
#####################################################################

Comments
WORK AROUND Java doesn't specify an particular scheduling order or fairness on threads contending for a java-level monitor. Refer to: * http://java.sun.com/j2se/1.5.0/docs/guide/vm/thread-priorities.html * Josh Bloch's "Effective Java" Item #51 * Comments in BUGID 4985566 Possible work-arounds: * Use one of the excellent "fair" lock constructs in java.util.concurrent. * Arrange for the application to restrict the set of threads eligible to compete for ownership of the monitor by volantarily blocking some subset of the threads.
30-08-2005

EVALUATION *** (#1 of 1): [ UNSAVED ] ###@###.###
30-08-2005