0

当我遇到使用等待/通知方法的示例时,我正在查看 Kathy Sierra 书中的线程章节:

 class ThreadA {
 public static void main(String [] args) {
 ThreadB b = new ThreadB();
 b.start();

 synchronized(b) {
 try {
    System.out.println("Waiting for b to complete...");
    b.wait();
     } catch (InterruptedException e) {}
 System.out.println("Total is: " + b.total);
 }
}
}

class ThreadB extends Thread { 
 int total;
 public void run() {
  synchronized(this) {
   for(int i=0;i<100;i++) {
   total += i;
   }
  notify();
 }
}
}

运行代码总是产生相同的输出:

等待 b 完成...总计:4950

我通过添加以下内容修改了 ThreadB 中 run() 的同步块:

System.out.println("ThreadB is executed"); 

问题是:为什么我不断得到

“等待b完成……”

“线程B被执行”

? 线程 b 是否有可能在主线程之前执行?

4

2 回答 2

5

线程 b 是否有可能在主线程之前执行?

是的,一点没错。

通常wait伴随一些谓词来防止此类问题。

例如,ThreadB 可以有一个变量表示它已经完成。在您的情况下,您可以检查总计是否不为 0。

synchronized (b) {
    try {
        System.out.println("Waiting for b to complete...");
        while (b.total == 0) {
            b.wait();
        }
    } catch (InterruptedException e) {
    }
    System.out.println("Total is: " + b.total);
}

这会在总读取相对于 ThreadB 中的写入创建之前发生的关系。

于 2013-04-12T19:40:27.310 回答
5

线程 b 是否有可能在主线程之前执行?

是的,这种可能性是存在的,尽管对于像这段代码这样的狭隘种族来说,这种可能性很小。

b.start()代码在获取 b 的监视器(同步块)之前调用。主线程有可能在该窗口期间被抢占,并且线程 B 将首先运行并获取该监视器。

在那种情况下,这个程序会挂起,因为主线程将wait()永远因为它错过了notify()来自线程 B的线程。

于 2013-04-12T19:48:36.020 回答