notify和notifyall显示等待多个线程的奇怪行为

时间:2015-07-13 15:54:06

标签: java multithreading notify

我以为我完全理解notifyAll()和notify()之间的区别是什么,但后来我突然遇到了这个代码,其输出我无法弄清楚。所以我需要一些帮助来理解奇怪的输出...

注意: - 评论后// 3并取消注释// 4输出为: -

Waiting for Calculations...
Waiting for Calculations...
Waiting for Calculations...
Total is : 4950

(这似乎是合理的,好像Thread()在3个等待线程之后启动并且它调用notifyAll()并且一个等待线程将获得锁并执行所以显示总数而其他仍然等待)

并在评论// 4并取消注释// 3输出后: -

Waiting for Calculations...
Waiting for Calculations...
Waiting for Calculations...
Total is : 4950
Total is : 4950

(这很奇怪我认为在第一次输出时,当Thread()在两个等待的线程之后启动时,一个将获得锁定并且只有一个应该显示总数。但是为什么第二个总计显示为输出。)

  

代码: -

class Reader extends Thread {
    Calculator c;

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

    public void run() {
        synchronized (c) {
            try {
                System.out.println("Waiting for calculations...");
                c.wait();
            }
            catch (InterruptedException e) {
            }

            System.out.println("Total is : " + c.total);
        }
    }

    public static void main(String arsg[]) {
        Calculator calculator = new Calculator();

        //Thread at 3rd and 4th position

        new Reader(calculator).start();
        new Reader(calculator).start();
        new Thread(calculator).start();  //3
        new Reader(calculator).start();
        //new Thread(calculator).start();    //4
    }
}

//----------------------------------------------------------------


class Calculator implements Runnable {

    int total;

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 100; i++) {
                total += i;
            }

            notifyAll();
        }
    }
}
  

代码经过修改并取自凯西塞拉   是自发唤醒的情况(其他唤醒是由jvm)

2 个答案:

答案 0 :(得分:3)

这是一个简单的竞争条件。在一种情况下,notifyAll只在一个线程调用wait后发生。在另一种情况下,notifyAll在两个线程调用wait之后发生。在不同的条件下,没有或所有其他线程可能/将会调用wait

notifyAll没有追溯性的工作。它只唤醒那些已经wait的线程,而不是那些稍后调用wait的线程。

答案 1 :(得分:0)

我已经得到了答案但仍然想发布我的最终修改代码,以解决我对这个问题的所有怀疑......

http://paste.ubuntu.com/11881225/

  

代码: -

class Reader extends Thread
{
    Calculator c;

public Reader(Calculator cal)
{
    c=cal;

}

public void run()
{
    synchronized(c)
    {
        try{
            System.out.println("Waiting for calculations...");
            c.wait();
        }
        catch(InterruptedException e){System.out.println("Exception occured");}

        System.out.println("Total is : "+c.total);
    }
}   

public static void main(String arsg[])
{
    Calculator calculator=new Calculator();

    new Reader(calculator).start();     
    new Reader(calculator).start();     
    new Reader(calculator).start();     

    new Thread(calculator).start(); // Change position of this line while experimenting


}
    }
    //----------------------------------------------------------------
    class Calculator implements Runnable

{
    int total;

public void run()
{
    synchronized(this)
    {
        for(int i=0;i<100;i++)
        {
            total+=i;
        }
        System.out.println("Before Notify");
        notifyAll();
        System.out.println("After Notify");
    }
}
}