wait()和sleep()之间的区别
线程中的wait()
和sleep()
有什么区别?
我的理解是wait()
ing线程仍处于运行模式并使用CPU周期,但sleep()
不会消耗任何CPU周期正确吗?
为什么我们同时wait()
和sleep()
:它们的实现在较低的层次上如何变化?
一个wait
可以被另一个线程唤醒,这个线程正在等待的监视器上notify
,而sleep
不能。 wait
(和notify
)也必须在监视器对象上synchronized
的块中发生,而sleep
不会:
Object mon = ...;
synchronized (mon) {
mon.wait();
}
此时当前正在执行的线程等待并释放监视器。 另一个线程可能会做
synchronized (mon) { mon.notify(); }
(在同一个mon
对象上),第一个线程(假设它是在显示器上等待的唯一线程)会唤醒。
如果显示器上有多个线程正在等待,您也可以调用notifyAll
- 这会唤醒所有线程。 但是,只有其中一个线程能够抓取显示器(请记住wait
处于synchronized
块中)并继续运行 - 其他线程将被阻止,直到它们可以获取显示器的锁定为止。
另一点是,你调用wait
Object
本身(即你等待对象的监视器),而你调用Thread
sleep
。
还有一点是,你可以从wait
获得虚假的唤醒(即等待恢复的线程没有明显的原因)。 您应该一直wait
同时按照以下条件旋转 :
synchronized {
while (!condition) { mon.wait(); }
}
还没有提到的一个关键区别是,在休眠时,线程不会释放它所持有的锁,而在等待释放时, wait()
对象上的锁被调用。
synchronized(LOCK) {
Thread.sleep(1000); // LOCK is held
}
synchronized(LOCK) {
LOCK.wait(); // LOCK is not held
}
我发现这个链接很有帮助(引用这篇文章)。 它将人类术语中的sleep()
, wait()
和yield()
之间的区别放在一起。 (万一这些链接死掉了,我已经在下面的文章中加入了额外的标记)
这一切最终都会进入操作系统的调度程序,调度程序会向进程和线程发送时间片。
sleep(n)
说: “我已经完成了我的时间片,请不要给我另一个至少n毫秒的时间。”操作系统甚至不会尝试安排睡眠线程,直到请求的时间过去。
yield()
表示“我完成了我的时间片,但我仍然有工作要做” 。操作系统可以自由地立即给线程另一个时间片,或者给一些其他线程或进程CPU让屈服线程放弃。
.wait()
说: “我完成了我的时间片。 不要再给我另一个时间片,直到有人调用notify()为止。“与sleep()
,除非有人调用notify()
(或者其他几个唤醒场景之一notify()
否则OS甚至不会尝试调度您的任务。
线程在执行阻塞IO并在其他几种情况下也会丢失时间片的剩余部分。 如果一个线程在整个时间片上工作,那么操作系统强制接受控制,就好像调用了yield()
一样,以便其他进程可以运行。
你很少需要yield()
,但是如果你有一个具有逻辑任务边界的计算量大的应用程序,那么插入一个yield()
可能会提高系统响应能力(以时间为代价 - 上下文切换,即使对于操作系统, t免费)。 像往常一样,针对您关心的目标进行衡量和测试。