这是《Java How To Program》中的例子:生产者与消费者的问题
public class HoldIntegerSynchronized {
   private int sharedInt = -1;
   private boolean writeable = true;  // condition variable   public synchronized void setSharedInt( int val )
   {
      while ( !writeable ) {  // not the producer's turn
         try {
            wait();  
         }
         catch ( InterruptedException e ) {
            e.printStackTrace();
         }
      }      System.err.println( Thread.currentThread().getName() +
         " setting sharedInt to " + val );
      sharedInt = val;      writeable = false;
      notify();  // tell a waiting thread to become ready
   }   public synchronized int getSharedInt()
   {
      while ( writeable ) {   // not the consumer's turn
         try {
            wait();
         }
         catch ( InterruptedException e ) {
            e.printStackTrace();
         }
      }      writeable = true;
      notify();  // tell a waiting thread to become ready      System.err.println( Thread.currentThread().getName() +
         " retrieving sharedInt value " + sharedInt );
      return sharedInt;
   }
}
public class ProduceInteger extends Thread {
   private HoldIntegerSynchronized pHold;   public ProduceInteger( HoldIntegerSynchronized h )
   {
      super( "ProduceInteger" );
      pHold = h;
   }   public void run()
   {
      for ( int count = 1; count <= 10; count++ ) {
         // sleep for a random interval
         try {
            Thread.sleep( (int) ( Math.random() * 3000 ) );
         }
         catch( InterruptedException e ) {
            System.err.println( e.toString() );
         }         pHold.setSharedInt( count );
      }      System.err.println( getName() +
         " finished producing values" +
         "\nTerminating " + getName() );
   }
}public class ConsumeInteger extends Thread {
   private HoldIntegerSynchronized cHold;   public ConsumeInteger( HoldIntegerSynchronized h )
   {
      super( "ConsumeInteger" );
      cHold = h;
   }   public void run()
   {
      int val, sum = 0;      do {
         // sleep for a random interval
         try {
            Thread.sleep( (int) ( Math.random() * 3000 ) );
         }
         catch( InterruptedException e ) {
            System.err.println( e.toString() );
         }         val = cHold.getSharedInt();
         sum += val;
      } while ( val != 10 );      System.err.println(
         getName() + " retrieved values totaling: " + sum +
         "\nTerminating " + getName() );
   }
}
请问在监控器HoldIntegerSynchronized 中,getSharedInt()中还没有返回sharedInt的值,监控器的条件变量writeable就被赋予“true”还调用了方法notigy()。那么不是就启动生产者的线程了,就可以调用setSharedInt()了,从而就可以更改shareInt的值了吗?那不是若getSharedInt()中还没有来得及返回sharedInt的值就又被新的只覆盖了吗??

解决方案 »

  1.   

    我的理解是,你所示的程序是写者优先,
    所以读者读的时候总是最新写入的值,
    getSharedInt()中返回sharedInt的值应该是最新的,监控器的条件变量writeable就被赋予“true”以后启动生产者的线程,它可以调用setSharedInt()了,从而就可以更改shareInt的值,所以getSharedInt()中还没有来得及返回的sharedInt的值是最新的当然也可以改成读优先,比如说,只要有读者在读或在等待,写者必须挂起,直到没有读者时,再唤醒写进程。
      

  2.   

    上万本图书免费下载
    http://www.netyi.net/in.asp?id=wxs_1128
      

  3.   

    genepoet(丁丁),
                
                  你可能心里面明白但是还是没有说得很清楚.我来说说我的想法吧(今天才想通的)。
             方法notify();只是将另外一个线程唤醒使之进入就绪态并没有转入执行态.所以要等到方法 getSharedInt()中的return后,才会切换到写者线程的执行态。所以就不可能出现楼主所说的覆盖的问题。   看来丁丁同学还是审题不清呀。hehe!
      

  4.   

    方法notify();只是将另外一个线程唤醒使之进入就绪态并没有转入执行态.所以要等到方法 getSharedInt()中的return后,才会切换到写者线程的执行态。所以就不可能出现楼主所说的覆盖的问题。“线程唤醒使之进入就绪态”不就意味着可能会运行么?
    那样话楼主的问题还是得不到解决哦,我也被捆饶了,不知道能不能该成把notify放在最后面,去掉return();
      

  5.   

    我今天看了1GoldenAge1(黄金时代) 的回贴,觉得他说得很好,线程进入就绪态并不意味可以直接占用CPU,而是要等到系统的调用。在此例中写者线程肯定要等到读者线程执行完后才能进行(当notify()时读者线程还没有释放CPU),所以不可能出现覆盖的问题。但是我写到这里的时候在想,如果写者的优先级高于读者又会怎样呢?会不会直接抢占CPU先为其服务呢(这时就出现了还没有retrun的情况)
    。在原来的《组成原理》课上学过,好像是如果要中断的话应该在一条指令执行完后,所以若在notify()唤醒写者后岂不是刚好写着就抢占了CPU吗(写着的优先级高的情况下)。
     
       是不是小弟概念不清?哪位大虾帮小弟解决一下。   在此谢谢 leihailin(exit(0);) 的关注,不过retrun是不能去掉的,要不拿来的读者(消费者)呀?  ^_^
      

  6.   

    看来楼主和我都没把线程同步的概念弄清楚,我查了一下,同一个类的同步方法都是互斥执行的,而在这个程序中,setSharedInt和getSharedInt前都加了synchronized,所以它们之间是互斥执行的,只要读者没有退出getSharedInt()方法,写者就无法执行setSharedInt()方法。
      

  7.   

    回genepoet(丁丁):
      
                     同一个类的同步方法都是互斥执行的,那一切都解决了.  ^_^看来你得的大分了。
    呵呵。