英文:
After executing wait(), how long does a thread wait if it does not get notified from other threads?
问题
在下面的示例中,由于主线程未从子线程得到通知,它应该永远等待。但实际上主线程正在执行,以下示例的输出是:
c
l
total: 19900
为什么主线程会被执行?
public class ThreadX extends Thread {
static int total = 0;
public void run() {
synchronized (this) {
for (int i = 0; i < 200; i++) {
total = total + i;
}
System.out.println("c");
}
}
public static void main(String[] args) throws InterruptedException {
ThreadX t = new ThreadX();
t.start();
synchronized (t) {
t.wait();
System.out.println("l");
}
System.out.println("total: " + total);
}
}
英文:
In the below example, as the main-thread is not getting notified from the child thread, it should wait forever. But the main-thread is getting executed and the output of the below example is:
c
l
total: 19900
Why is the main-thread getting executed?
public class ThreadX extends Thread {
static int total = 0;
public void run() {
synchronized (this) {
for (int i = 0; i < 200; i++) {
total = total + i;
}
System.out.println("c");
}
}
public static void main(String[] args) throws InterruptedException {
ThreadX t = new ThreadX();
t.start();
synchronized (t) {
t.wait();
System.out.println("l");
}
System.out.println("total: " + total);
}
}
答案1
得分: 9
Answer to the question-body
> [...] 当线程终止时,将调用 this.notifyAll
方法。[...]
注意,Thread#join()
使用参数 0
调用该函数,意味着永远等待。
> [...] 超时值为 0 表示无限等待。
因此在你的情况下,t
在终止时只是调用了 notifyAll
,这会通知正在等待 t
的主线程。
这种不直观的行为是他们在文档中写下以下内容的原因:
> 建议应用程序不要在 Thread
实例上使用 wait
、notify
或 notifyAll
。
Answer to the question-title
查看 Object#wait
(或JLS(17.2.1. Wait)):
> 线程可能会在没有收到通知、中断或超时的情况下被唤醒,这称为虚假唤醒。虽然这在实践中很少会发生,但应用程序必须通过测试应该导致线程被唤醒的条件,并在条件不满足时继续等待来防范这种情况。
因此,在Java中,线程可能随时被唤醒。虽然虚假唤醒不太可能发生,但确实有可能发生。
英文:
Answer to the question-body
Check out Thread#join(long)
:
> [...] As a thread terminates the this.notifyAll
method is invoked. [...]
Notice that Thread#join()
calls that function with 0
, which means forever.
> [...] A timeout of 0 means to wait forever.
So in your case here t
just calls notifyAll
when it terminates, which notifies the main-thread that is waiting on t
.
This unintuitive behaviour is the reason why they write the following in the documentation:
> It is recommended that applications not use wait
, notify
, or notifyAll
on Thread
instances.
Answer to the question-title
Check out Object#wait
(or JLS (17.2.1. Wait)):
> A thread can wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied.
So threads in Java can wake up at any time. A spurious wakeup is not very likely but it can happen.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论