public class Calculator extends Thread {
int total;

public void run(){
synchronized(this){
for(int i=0;i<10;i++)
total +=i;
//notifyAll();
}
}
}
public class Reader extends Thread { /**
 * @param args
 */
public static void main(String[] args) {
Calculator c = new Calculator();
new Reader(c).start();
new Reader(c).start();
new Reader(c).start();
c.start(); }
Calculator c;

public Reader(Calculator calc){
c = calc;
}

public void run(){
synchronized(c){
try{
System.out.println("waiting for calculation...");
c.wait();
}catch(InterruptedException e){}
System.out.println("total in reader is: "+c.total);
}
}
}
在运行Reader的时候,程序仍然能输出3个45,可是我已经把Calculator类的notifyAll()给注释掉了,我觉得应该输出不了这个答案了,运行时应该一直在等待才对啊,请各路高手帮忙解释一下,谢谢了!

解决方案 »

  1.   

    我想,是在Caculator 的run方法中对this进行啦同步操作。这个操作对没个Caculator对象都有效。
    在它的run运行完后,自然就释放啦锁。
      

  2.   

    如果去掉Reader类main方法中的c.start(),则运行时将一致等待;三个Reader对象分别拥有一把c锁,而每一个c对象都指向了同一个cal对象
      

  3.   

    或者是说三个Reader对象拥有同一把c锁,当c.wait()时候当前线程会失去c锁,从而都进入到等待c锁的等待队列中以备唤醒,而Calculator中的run方法也进行了同步,当它执行完了就会放弃对c的拥有权。
      

  4.   


    Calculator的run方法执行完是会放弃对c的拥有权,问题是它没有调用notifyAll()的话也就没有启动那3个在等待池中等待的Reader,我就是不明白这3个Reader是怎么又能输出后面的那句打印的
    希望再详细讲讲,谢谢!
      

  5.   

    There's also a possible situation called spontaneous wakeup that may exist in some
    situations—a thread may wake up even though no code has called notify()
    or notifyAll(). (At least, no code you know about has called these methods.
    Sometimes the JVM may call notify() for reasons of its own, or code in some other
    class calls it for reasons you just don't know.)                                       
      

  6.   

      当c对象的run方法同步后,当它执行完了就会放弃对象上的锁...JVM可能明白对象上的run已经执行完且已放弃对象上的锁,自己隐式地调用了notifyAll(),可能你不知道...我是怎么理解的...就看你自己理解的问题了...
      

  7.   

    那我要是都不手动的调用notify()/notifyAll()了呢?JVM是否可以每次都自动的帮我把活干了?能拿中文回帖么,英文不是特好,谢谢:)
      

  8.   

    ...我是从原版书上copy过来的...呵呵~我怕我翻译过来会误导你...那本书上说:有一种可能存在的情况,即使没有代码调用notify()或者notfyAll(),线程也会被通知到.
    有些时候JVM会因为它自己的理由和原因去请求notify(),只是你不知道...
    和wait()不同,在对象上调用notify(),并不是立刻放弃对象上的锁并通知等待线程的...而是当我这个代码块执行完才解锁并通知线程...因此,我有理由相信...JVM明白这个对象能解锁了,就表示对该对象的操作已经完毕,即使你没有调用notify(),我也会去通知等待线程...可能是出于JVM的安全机制考虑吧,可能有些时候程序员忘了调了,但明明操作是成功的...导致了异常,代码量巨大的话似乎很难察觉这个问题...当然,这只是我个人观点...毕竟这本书上也没有说明JVM它调用notify()的个人理由是什么...如果你想知道的话,推荐你深入了解下JVM...
    最好还是手动的调吧!毕竟自动调是没有保障的,谁也不能够保证...
      

  9.   

    我觉的是只有一把锁,第一个用完之后会放弃锁给下一个用,加notifyall()与不加的区别在于,如果不加那下面两个线程就死等着,直到得到那把锁,如果永远得不到就变死锁了。如果加了的话,下面两个可以不用等,可以自己去做自己的事,等有锁了会通知给他们