为什么更喜欢等待/通知而不是循环



我对等待/通知的优点有一些误解。据我所知,处理器核心在这两种情况下都不会有任何帮助,那么写复杂的等待/通知块代码而不仅仅是在循环中等待的原因是什么?我很清楚,当两个线程只在一个核心上执行时,等待/通知不会占用处理器时间。

"循环中的等待"通常被称为"繁忙循环"或"busy wait":

 while ( ! condition()) {
     // do nothing
 }
 workThatDependsOnConditionBeingTrue();

这是对其他可能需要CPU时间的线程或进程的不尊重(如果可以的话,它需要100%的时间)。因此,还有另一种变体:

 while ( ! condition()) {
     sleepForShortInterval();
     // do nothing
 }
 workThatDependsOnConditionBeingTrue();

这种变体中的小睡眠会显著降低CPU使用率,即使它的长度约为100ms,除非你的应用程序是实时的,否则这一点应该不会引起注意。

注意,在条件实际变为真时和sleepForShortInterval()结束时之间通常会有延迟。如果为了对他人更有礼貌,你睡得更长,那么延迟就会增加。这在实时场景中通常是不可接受的。

假设condition()正在检查的任何内容都是从另一个线程更改的,那么实现这一点的好方法是让其他线程在完成您正在等待的内容时唤醒您。更干净的代码,没有浪费的CPU,没有延迟。

当然,实现繁忙等待会更快,而且对于快速"死亡"的情况可能是合理的。

注意,在condition()可以更改为false和true的多线程场景中,您需要在whileworkThatDependsOnConditionBeingTrue()之间保护代码,以避免其他线程在这个精确的时间点更改其值(这被称为race codition,事后很难调试)。

我想你几乎通过说来回答你的问题

我很清楚,在这种情况下,等待/通知不会占用处理器的时间。

我唯一想补充的是,无论是单核还是多核,这都是正确的。与while循环或定期检查相比,wait/notify不会使cpu处于繁忙等待状态。

为什么不运行core而等待?在任何情况下都没有有用的工作,并且当core处于等待状态时,您无法使用它。

我认为您是从单个应用程序的角度来看待它的,其中只有一个应用程序和一个线程在运行。从现实世界中的应用程序(如web/应用程序服务器或独立应用程序)中想象一下,其中有many threads正在运行,competing for cpu cycles-你可以see the advantage of wait/notify.。你绝对不希望哪怕是一个线程也只是忙于等待并消耗cpu周期。

即使是在系统上运行的单个应用程序/线程,也总是有操作系统进程及其相关进程在竞争CPU周期。您不希望他们因为应用程序正在执行while busy-wait而饿死他们。

引用Gordon的评论

在循环中等待,就像你建议的那样,你不断地检查你正在等待的事情是否已经完成,这是浪费,如果你使用睡眠,你只是在猜测时间,而等待/通知你会一直闲置,直到你正在等待告诉你已经完成。

通常,您的应用程序不是唯一在CPU上运行的应用程序。首先,使用非旋转等待是对其他进程/线程的礼貌行为,这些进程/线程正在争夺CPU,以便完成一些有用的工作。CPU调度程序无法先验地知道线程是要做一些有用的事情,还是只是在错误的标志上旋转。所以,它不能基于此调整自己,除非你告诉它你不想被运行,因为你没有什么可做的

事实上,繁忙的等待比让线程休眠更快,这就是为什么wait()方法通常以混合方式实现的原因。它先是旋转了一会儿,然后就睡着了。

此外,它不仅仅是在循环中等待。你仍然需要同步访问你正在旋转的资源。否则,你将成为种族条件的受害者。

如果您觉得需要一个更简单的接口,也可以考虑使用CyclicBarrierCountDownLatchSynchronousQueue

最新更新