在线程程序中使用wait()时,notify()语句的意义是什么

时间:2015-09-18 01:46:07

标签: java multithreading

public class ThreadA {

    public static void main(String[] args) {
        ThreadB threadB = new ThreadB();
        threadB.start();
        synchronized (threadB) {
            try {
                threadB.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("the total is ====>"+threadB.total);

    }
}
class ThreadB extends Thread
{
    int total;
    public void run(){
        synchronized (this) {
            for(int i =0; i<5;i++)
            {
                System.out.println("lets add===>"+i);
                total+= i;
            }
            notify(); // line no.31
            System.out.println("after notify but within lock");

        }
        System.out.println("after notify but outside lock");

    }
}
    
output : 
lets add===>0
lets add===>1
lets add===>2
lets add===>3
lets add===>4
after notify but within lock
the total is ====>10
after notify but outside lock

我的问题:控制不应该在第31行之后立即回到“主”线程。理想情况下不应该打印 - “允许添加===&gt; 4”后立即“总数是====&gt; 10”?

为什么它执行synchronized块中的所有语句而不管第31行中的notify()语句?

2 个答案:

答案 0 :(得分:0)

最后几行的顺序总是不一样。它取决于线程的调度方式,并且根据您拥有的代码无法保证。你执行notify wait的那一刻结束了,所以任何线程都可以按任何顺序运行。但是after notify but within lock在锁定范围内,所以即使主线程被执行锁定也无法做任何事情

答案 1 :(得分:0)

  

我的问题:控制不应该在第31行之后立即回到“主”线程。

你要求不可能的事。调用notify的线程仍在同步块中。一旦另一个线程完成等待,它就会回到同步块中。所以你要求的是同时要求两个线程在同一个对象上的同步块中,这正是这些块禁止的。

    synchronized (threadB) {
        try {
            threadB.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.println("the total is ====>"+threadB.total);

所以这段代码就是这样做的:

  1. 输入synchronized block。
  2. 致电wait
  3. 退出同步块。
  4. 打印总数。
  5. 注意:

    1. 我们不能退出同步块,除非我们在同步块中;以及

    2. 在我们从wait返回之前,我们无法退出已同步的块;从而

    3. 我们不能从wait进入打印总数而不是在同步块中,因此当另一个线程保留在synchronized块中时我们不能这样做,否则将会有两个线程同步阻止。

    4. 现在看看这段代码:

              notify(); // line no.31
              System.out.println("after notify but within lock");
          } // exit synchronized block
      

      因此,任何通知另一个线程的线程在打印之前都不会保留其同步块。因此,通知的线程在打印之前不能退出其同步块。