下面是我在本地计算机上运行时成功完成执行的代码段。
我无法理解为什么这个线程不会进入无限等待状态?
public class Job extends Thread {
private int counter;
@Override
public void run() {
synchronized (this) {
for (int i = 0; i < 100000; i++) {
counter++;
}
this.notifyAll();
}
}
public static void main(String[] args) throws InterruptedException {
Job job = new Job();
job.start();
synchronized (job) {
job.wait();
}
System.out.println(job.counter);
}
}
是否有任何保证,上述代码将始终在每种情况下完成执行?任何人都可以澄清一下吗?
答案 0 :(得分:1)
看起来你手上有Race Condition
- 这完全取决于首先发生的synchronized(job)
- 主线程中的那个或工作中的那个。
答案 1 :(得分:0)
有几种可能性
synchronized
和wait()
。在这种情况下,程序将终止,因为job
Thread
会在notify()
对象上调用synchronized
。job
Thread
首先进入synchronized
阻止,并在主notify()
来电Thread
之前致电wait()
,即。{ main Thread
不能,因为它在synchronized
块等待。这将阻止该应用程序,因为主Thread
将无法从wait()
电话返回。答案 2 :(得分:0)
我无法理解为什么这个线程不会进入无限等待 状态?
如果在this.notifyAll()
之前调用job.wait()
,就会发生这种情况。
添加一个标志以测试完成,如下所示:
public class Job extends Thread {
private int counter;
private boolean finished = false;
@Override
public void run() {
synchronized (this) {
for (int i = 0; i < 100000; i++) {
counter++;
}
finished = true;
this.notifyAll();
}
}
public static void main(String[] args) throws InterruptedException {
Job job = new Job();
job.start();
synchronized (job) {
while (!job.finished)
job.wait();
}
System.out.println(job.counter);
}
}
这样你就可以保证程序不会遇到竞争条件而且会永远等待。另请注意,您现在受到spurious wakeups的保护。
答案 3 :(得分:0)
除了虚假的唤醒问题(大多数情况下不应该影响这种简单的使用),你应该期望代码总是完成。
您似乎缺少的一件事是job.wait();
释放锁定,允许执行另一个synchronized
块并调用notifyAll()
。此时,wait
醒来,主要方法退出。