问题

线程中的wait()sleep()有什么区别?

我的理解是wait()-ing线程仍处于运行模式并且使用CPU周期但是sleep()-ing不会消耗任何CPU周期正确吗?

为什么我们有wait()sleep():它们的实现如何在较低的水平上变化?


#1 热门回答(730 赞)

一个“等待”可以被正在等待的显示器上的另一个调用“notify”的线程“唤醒”,而“sleep”则不能。还有一个wait(和notify)必须发生在监视器对象上的synchronized块中,而sleep则不会:

Object mon = ...;
synchronized (mon) {
    mon.wait();
}

此时当前执行的线程等待并释放监视器。另一个线程可能会做

synchronized (mon) { mon.notify(); }

(在相同的mon对象上)和第一个线程(假设它是在监视器上等待的唯一线程)将被唤醒。

如果监视器上有多个线程正在等待,您也可以调用notifyAll - 这会唤醒它们。但是,只有一个线程能够获取监视器(请记住,“wait”处于“synchronized”块中)并继续运行 - 其他线程将被阻塞,直到它们可以获取监视器的锁定。

另一点是你在Object本身上调用wait(即你在对象的监视器上等待),而在Thread上调用sleep

还有一点是,你可以从`等待'唤醒虚拟机(即正在等待的线程没有明显的原因恢复)。您应该等待,同时按照以下条件旋转:

synchronized {
    while (!condition) { mon.wait(); }
}

#2 热门回答(281 赞)

还没有提到的一个关键区别是,在睡眠时,线程不会释放它保存的锁,而在等待释放时,会调用“wait()”对象上的锁。

synchronized(LOCK) {
    Thread.sleep(1000); // LOCK is held
}


synchronized(LOCK) {
    LOCK.wait(); // LOCK is not held
}

#3 热门回答(196 赞)

我发现this link有帮助(其中引用this post)。它将人类术语中的“sleep()”,“wait()”和“yield()”区别开来(如果链接死掉了,我会在后面添加标记)

这一切最终都会进入操作系统的调度程序,该调度程序将进程和线程的时间片交给操作系统。 sleep(n)说:“我已经完成了我的时间片,请不要给我另一个至少n毫秒的时间。”操作系统甚至不会尝试安排睡眠线程,直到请求的时间过去。 yield()表示“我完成了我的时间片,但我仍然有工作要做”。操作系统可以自由地立即给线程另一个时间片,或者给一些其他线程或进程CPU让屈服线程放弃。 .wait()说:“我完成了我的时间片。不要再给我另一个时间片,直到有人调用notify()为止。“与sleep()一样,除非有人调用notify()(或者其他几个唤醒场景之一),否则OS甚至不会尝试调度您的任务。线程在执行阻塞IO并在其他几种情况下也会丢失时间片的剩余部分。如果一个线程在整个时间片上工作,那么操作系统强制接受控制,就好像调用了yield()一样,以便其他进程可以运行。你很少需要yield(),但是如果你有一个具有逻辑任务边界的计算量大的应用程序,那么插入一个yield()可能会提高系统响应能力(以时间为代价 - 上下文切换,即使对于操作系统,免费)。一如既往地衡量和测试您关心的目标。


原文链接