当我遇到使用wait / notify方法的示例时,我正在查看Kathy Sierra书中的Threading章节:
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()的synchronized块System.out.println("ThreadB is executed");
问题是:为什么我要继续
“等待b完成......”
之前
“执行ThreadB”
?是不是有可能在主线程之前执行线程b?
答案 0 :(得分: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中的写入相关的总计上创建一个先发生的关系。
答案 1 :(得分:5)
是否有可能在主线程之前执行线程b?
是的,存在这种可能性,尽管这种可能性很小,例如这段代码中的那种。
代码在获取b的监视器(同步块)之前调用b.start()
。主线程有可能在该窗口期间被抢占,并且线程B将首先运行并获取该监视器。
在这种情况下,这个程序会挂起,因为主线程永远wait()
,因为它错过了线程B中的notify()
。