Java 为什么线程不进入无限时间等待状态?
下面是我在本地机器上运行时成功完成执行的代码段 我无法理解为什么这个线程没有进入无限等待状态Java 为什么线程不进入无限时间等待状态?,java,multithreading,Java,Multithreading,下面是我在本地机器上运行时成功完成执行的代码段 我无法理解为什么这个线程没有进入无限等待状态 public class Job extends Thread { private int counter; @Override public void run() { synchronized (this) { for (int i = 0; i < 100000; i++) { counter+
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);
}
}
公共类作业扩展线程{
专用int计数器;
@凌驾
公开募捐{
已同步(此){
对于(int i=0;i<100000;i++){
计数器++;
}
this.notifyAll();
}
}
公共静态void main(字符串[]args)引发InterruptedException{
作业=新作业();
job.start();
已同步(作业){
job.wait();
}
系统输出打印LN(作业计数器);
}
}
有没有保证上述代码在任何情况下都能完成执行?有人能澄清一下吗?有几种可能性
synchronized
和wait()
s。在这种情况下,程序将终止,因为作业
线程
将调用同步
对象上的通知()
作业
线程
首先进入同步
块,并在主线程
调用等待()
之前调用通知()
,即主线程
无法,因为它在同步
块等待。这将阻止应用程序,因为主线程将无法从wait()
调用返回
看起来你手头确实有一个任务-这取决于哪个
同步(作业)
首先发生-是在主线程中还是在作业中
我不明白为什么这个线程没有进入无限等待
地位
它可以,如果在job.wait()
之前调用this.notifyAll()
,就会发生这种情况
添加一个标记以测试是否完成,如下所示:
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);
}
}
公共类作业扩展线程{
专用int计数器;
private boolean finished=false;
@凌驾
公开募捐{
已同步(此){
对于(int i=0;i<100000;i++){
计数器++;
}
完成=正确;
this.notifyAll();
}
}
公共静态void main(字符串[]args)引发InterruptedException{
作业=新作业();
job.start();
已同步(作业){
而(!作业。已完成)
job.wait();
}
系统输出打印LN(作业计数器);
}
}
这样,您就可以保证程序不会陷入竞争状态,并将永远等待。还要注意的是,现在您可以保护自己不受影响。除了虚假的唤醒问题(大多数情况下不会影响这种简单的使用)之外,您应该希望代码始终能够完成
您似乎缺少的一件事是
job.wait()
释放锁,允许执行另一个已同步的
块,并调用notifyAll()
。此时,wait
唤醒,main方法退出。作业的run方法上的睡眠不会导致死锁吗?@zmbq我不这么认为,因为当它切换上下文时,另一个线程仍在等待,因此它将切换回。只有一个线程可以同时进入synchronized
块,对吗?如果作业执行,则一切正常(作业运行循环、通知并退出)。如果它是主线程,作业将无法运行。我错过什么了吗?@zmbq不,你知道了。我想这就是我在问题中写的。如果主线程休眠,作业线程将进入并完成其同步。它将在主线程wait()
sKeep之前发出通知。记住,wait方法将在阻塞之前释放同步对象的所有权。我想这就是你丢失的链接。等等,()可能会在没有通知的情况下冒然醒来。这就是为什么您应该始终使用notify更改同步块中的状态,并始终使用wait()更改循环中的状态更改。在您的代码中,没有任何保证。