Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-1214825

Function/Doc: Thread synchronization: starvation

    XMLWordPrintable

Details

    • sparc
    • solaris_2.3

    Description


      In the typical thread synchronization example : producer-consumer problem.
      producer and consumer share a limited buffer.

      One producer and two consumers access the buffer. Although consumer cth2
      has the same priority as the consumer cth1, consumer th2 never has chance
      to run (starvation) until the consumer cth1 finishes. This problem is
      caused by the simple prority and FIFO scheduling. It may need one aging
      mechanism to make scheduling fair.
       
      Also the documentary on notify() and wait() needs to explain the thread
      synchronization model such as the highest priority waiting thread is
      chosen to run next when entering monitor.
      It seems to me that priority inheritance policy is taken when a thread
      attempts to enter the monitor so that the real time thread gets a
      bounded delay(execution time of the critical section code). This needs
      to be detailed in the documentary.


      ----------code---------
      class pcbuffer {
        private threadsafe int buf_size;
        private threadsafe int stock;
        private long prod_time ;
        private long cons_time;
        private boolean debugflag;
        private boolean waitflag;
        private boolean failed;
        private char execflow[];
        private int seq; // sequence number of access to critical section

        pcbuffer( )
        {
          buf_size = 20;
          stock = 0;
          prod_time = 0;
          cons_time = 0;
          debugflag = true;
          waitflag = true;
          failed = false;
          execflow = new char[100];
          seq = 0;
        }
        public synchronized void put()
        {
          if ( stock < buf_size ) {
              if ( debugflag )
      System.out.println(Thread.currentThread().getName() + " attempts to put one ball\\
       from buffer successfully at " + System.currentTimeMillis());
      execflow[seq++] = 'p';
            stock++;
      notifyAll();

      waitflag = false;
      //notify();
          }
          else {
            if ( debugflag )
          System.out.println(Thread.currentThread().getName() + " attempts to put one ball\\
       from buffer failed at " + System.currentTimeMillis() + " wait ....");
            execflow[seq++] = 'p';
            while (stock > buf_size ) wait();
            stock++;
            //notifyAll();
            if ( debugflag )
      System.out.println(Thread.currentThread().getName() + " is waken up m waiting\\
        at " + System.currentTimeMillis());
            execflow[seq++] = 'p';
          }
        }


        public synchronized void pop()
        {
          if ( stock > 0 ) {
            execflow[seq++] = 'c';
            stock--;
            if ( debugflag )
          System.out.println(Thread.currentThread().getName() + " attempts to take one ball\\
       from buffer successfully at " + System.currentTimeMillis());

            //notify();
            notifyAll();
          }
          else
            {
      long t1, t2;

      t1 = System.currentTimeMillis();
      execflow[seq++] = 'c';
      if ( debugflag )
          System.out.println(Thread.currentThread().getName() + " attempts to take one ball\\
       from buffer failed at " + t1);
            waitflag = true;

      // note while(..) is necessary to make sure stock > 0 after being waken up
            while ( stock == 0 )
      {
      System.out.println(Thread.currentThread().getName() + " waiting...");
      wait();
      t2 = System.currentTimeMillis();
            if ( debugflag )
      System.out.println(Thread.currentThread().getName() + " is waken up from waiting\\
        at " + t2);
              }
            stock--;

         
      //notifyAll();

              execflow[seq++] = 'c';

      // make sure producer changes the flag.
      if ( waitflag )
      {
      failed = true;
      }
      else
      {
      failed = false;
      }
           }
          }

         public int getstock() { return stock; }
        
         public boolean isok()
         {
           boolean cflow = true;

           // here we don't check the timing of execution flow.
           
            return ( stock == 5 && failed == false && cflow);
         }
      }

      /**
       * Thread producer puts one ball into the buffer.
       * overriding the run().
       */
      class producer extends Thread {

        private pcbuffer buf;

        producer(pcbuffer buf)
        {
          this.buf = buf;
        }
        
        public void run() {
          int i = 0;
          while( i < 10) {
      buf.put();
      System.out.println(getName() + ": The number of balls in buffer = " + buf.getstock());
                 i++;
                 //Thread.sleep( 20);
          }
      }
      }

      class consumer extends Thread {

        private pcbuffer buf

      Attachments

        Activity

          People

            tlindholsunw Timothy Lindholm (Inactive)
            duke J. Duke
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: