为什么 'notify' 唤醒了所有等待的线程,尽管只有一个线程应该受到影响?
Why does 'notify' wake up all waiting threads although only one thread should be affected?
在下面的代码中,两个消费者线程启动并等待。生产者线程在那之后开始(很可能)并调用 'notify'。所有线程都使用生产者作为监视器。
Thread producer = new Thread() {
@Override
public void run() {
synchronized (this) {
System.out.printf("notify at %d %n", getId());
notify();
}
}
};
Runnable consumer = () -> {
try {
synchronized (producer) {
long id = Thread.currentThread().getId();
System.out.printf("wait at %d %n", id);
producer.wait();
System.out.printf("awakened: %d %n", id);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Stream.generate( () -> consumer )
.limit(2)
.map(Thread::new)
.forEach(Thread::start);
Thread.sleep(3000); // consumer threads are (likely) waiting
producer.start();
来自 Object.notify 的 javadoc:
Wakes up a single thread that is waiting on this object's monitor.
代码产生这个(或类似的)输出:
wait at 13
wait at 14
notify at 12
awakened: 13
awakened: 14
重点是两个消费者线程都被唤醒,而不是只有一个。为什么?
在 Windows 10、64 位下使用 OpenJDK 运行时环境 AdoptOpenJDK(内部版本 11.0.5+10)编译和测试。
提前致谢!
问题是您使用 Thread
作为监视器而不是任意 Object
。
Thread
在内部使用信号,如 Thread.join
:
中所述
As a thread terminates the this.notifyAll
method is invoked. It is recommended that applications not use wait
, notify
, or notifyAll
on Thread
instances.
一般建议始终使用专用对象 wait
/notify
,其他代码无法访问该对象以避免 "spurious" 像这样通知或等待。
在下面的代码中,两个消费者线程启动并等待。生产者线程在那之后开始(很可能)并调用 'notify'。所有线程都使用生产者作为监视器。
Thread producer = new Thread() {
@Override
public void run() {
synchronized (this) {
System.out.printf("notify at %d %n", getId());
notify();
}
}
};
Runnable consumer = () -> {
try {
synchronized (producer) {
long id = Thread.currentThread().getId();
System.out.printf("wait at %d %n", id);
producer.wait();
System.out.printf("awakened: %d %n", id);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Stream.generate( () -> consumer )
.limit(2)
.map(Thread::new)
.forEach(Thread::start);
Thread.sleep(3000); // consumer threads are (likely) waiting
producer.start();
来自 Object.notify 的 javadoc:
Wakes up a single thread that is waiting on this object's monitor.
代码产生这个(或类似的)输出:
wait at 13
wait at 14
notify at 12
awakened: 13
awakened: 14
重点是两个消费者线程都被唤醒,而不是只有一个。为什么?
在 Windows 10、64 位下使用 OpenJDK 运行时环境 AdoptOpenJDK(内部版本 11.0.5+10)编译和测试。
提前致谢!
问题是您使用 Thread
作为监视器而不是任意 Object
。
Thread
在内部使用信号,如 Thread.join
:
As a thread terminates the
this.notifyAll
method is invoked. It is recommended that applications not usewait
,notify
, ornotifyAll
onThread
instances.
一般建议始终使用专用对象 wait
/notify
,其他代码无法访问该对象以避免 "spurious" 像这样通知或等待。