使用notify()和notifyAll()在代码中不起作用

时间:2013-07-12 10:20:18

标签: java multithreading wait notify synchronize

我粘贴了下面的代码。这已经足够评论了。 清除wait()。来到这里时它跳到另一个街区。那部分我是橡木的。 我怀疑的是为什么我们使用notify和notifyAll()。如果你从下面的代码中删除这两个,它可以正常工作。

class Reader extends Thread{
    Calculator c;
    //here we didn't write no-arg constructor.  Note this.
    // one - arg constructor.
    public Reader(Calculator calc){
        c = calc;
    }
    public void run(){
        synchronized(c){
        // 2. Acquiring the object lock and executes this code of block.
            try{
                System.out.println("Waiting for calculation...");
                c.wait();
                // 3.  Release the object lock and moves to the second synchronize block below
                // 6. Later the object get the lock here and moves on.
            }catch(InterruptedException e){
            }
            System.out.println("Total is: "+c.total);
        }
    }
    public static void main(String[] args){
        //Instantiating new with no-arg.  One more doubt,  How this work without no-arg constructor above.  Please explain.
        Calculator calculator = new Calculator();
        //Instantiating new with one-arg
        new Reader(calculator).start();
        new Reader(calculator).start();
        new Reader(calculator).start();
        // 1. Once you start here it will goto first synchronized code block above
        calculator.start();
    }
}

class Calculator extends Thread{
    int total;

    public void run(){
        synchronized(this){
        // 4. This block acquires that object lock and executes the code block below.

            for(int i=0;i<100;i++){
                total +=i;
            }
            // 5.  As per documentation,  If we give notify() it will release the object lock to only one thread object of its choice.
            //     If we use notifyAll(); it will release the object lock to all the three thread object.
            notify();
            // My doubt here is without using the notify or notifyAll it is working fine.
            // As per docs if we use notify() only one object should get the lock.  That is also not working here.
        }
    }
}

3 个答案:

答案 0 :(得分:5)

一般评论:the javadoc of Object#wait声明

  

与在一个参数版本中一样,中断和虚假唤醒是可能的,并且此方法应始终在循环中使用。

因此,等待线程可以在没有得到通知的情况下唤醒,并且您的设计应该通过在循环中等待并检查退出条件来考虑这一点(参见javadoc中的示例)。


但是,在您的情况下,问题略有不同。根据{{​​3}}:

  

当一个线程终止时,将调用this.notifyAll方法。建议应用程序不要在Thread实例上使用wait,notify或notifyAll。

因此,当您的计算器完成时,它会调用this.notifyAll()并唤醒所有等待的线程。


如何解决?

您应该在计算器中使用单独的锁定对象,类似于:private final Object lock = new Object();,并为读者提供吸气剂。

答案 1 :(得分:1)

无法保证线程开始运行的顺序。如果计算器首先运行,则其notify将丢失,并且不会通知任何一个Reader。

答案 2 :(得分:1)

以上是上述程序的更正版本,它对notify()和notifyAll()有一定意义。 这里我实现了Runnable而不是扩展Threads。这是我做过的唯一改变。它工作得很好。

class Reader implements Runnable{
    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 is: "+c.total);
        }
    }
    public static void main(String[] args){

        Calculator calculator = new Calculator();

        Reader read = new Reader(calculator);

        Thread thr  = new Thread(read);
        Thread thr1 = new Thread(read);
        Thread thr2 = new Thread(read);

        thr.start();
        thr1.start();
        thr2.start();
        new Thread(calculator).start(); 
    }
}
class Calculator implements Runnable{
    int total;
    public void run(){
    System.out.println("Entered Calculator");
        synchronized(this){
            for(int i=0;i<20;i++){
                total +=i;
            }
                notifyAll();
        }
    }
}
相关问题