a.u*_*u.r 0 java thread-safety race-condition
当我遇到使用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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
运行代码总是产生相同的输出:
等待b完成......总计是:4950
我在ThreadB中修改了run()的synchronized块,添加:
System.out.println("ThreadB is executed");
Run Code Online (Sandbox Code Playgroud)
问题是:我为什么一直这样做
"等待b完成......"
之前
"执行ThreadB"
?是不是有可能在主线程之前执行线程b?
是不是有可能在主线程之前执行线程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);
}
Run Code Online (Sandbox Code Playgroud)
这会在读取总计时创建与ThreadB中的写入相关的先发生关系.
是不是有可能在主线程之前执行线程b?
是的,存在这种可能性,尽管这种可能性很小,例如这段代码中的那种.
代码b.start()在获取b的监视器(同步块)之前调用.主线程有可能在该窗口期间被抢占,并且线程B将首先运行并获取该监视器.
在那种情况下,这个程序会挂起,因为主线程将wait()永远,因为它错过了notify()来自线程B.
| 归档时间: |
|
| 查看次数: |
153 次 |
| 最近记录: |