我知道忙碌等待的实现。这是一个像这样的死亡循环:
//main thread
while (true) {
msg = msgQueue.next();
msg.runnable.run();
}
//....msg queue
public Message next() {
while (true) {
if (!queue.isEmpty()) {
return queue.dequeue();
}
}
}
所以,方法" next()"只是看起来像被阻止,实际上它一直在运行。 这被称为"忙着等待#34;在书上。
以及"进程被屏蔽的内容"?它的实施细节怎么样? 还是一个死循环?或其他一些人?像信号机制一样?
例如: 猫xxx | grep" abc"
过程" cat"读取文件并输出。流程" grep"等待来自" cat"。
的输入所以在" cat"之前输出数据," grep"应该被阻止,等待输入并继续。 关于这个"阻止"的详细信息,死循环一直读取输入流?或者真的停止运行,等待信号唤醒它运行?
答案 0 :(得分:8)
差异主要在于流程发生的情况:
<强> 1。忙碌的等待
一个忙着等待的过程基本上是在不停地运行,问“我们还在吗?我们还在吗?现在怎么样,我们还在吗?”这个问题消耗了100%的CPU周期:
bool are_we_there = false;
while(!are_we_there)
{
// ask if we're there (without blocking)
are_we_there = ask_if_we_are_there();
}
<强> 2。被阻止(或阻止)
的进程被阻止的进程被操作系统暂停,并在其正在等待的数据可用时自动通知。如果没有操作系统的帮助,这是无法实现的。
示例是一个等待长时间运行的I / O操作或等待计时器到期的进程:
// use a system call to create a waitable timer
var timer = CreateWaitableTime()
// use another system call that waits on a waitable object
WaitFor(timer); // this will block the current thread until the timer is signaled
// .. some time in the future, the timer might expire and it's object will be signaled
// causing the WaitFor(timer) call to resume operation
<强>更新强>
可以在操作系统级别以不同方式实现可等对象,但通常它可能是在操作系统中注册的硬件计时器,中断和可等对象列表的组合通过客户端代码。当发生中断时,将调用操作系统的中断处理程序,该处理程序将扫描与该事件相关联的任何可等待对象,并调用某些回调,这最终将发出可等待对象的信号(将它们放入一个信号状态)。这是一种过度简化,但如果您想了解更多信息,可以阅读中断和硬件定时器。
答案 1 :(得分:0)
当您说“一个进程被阻止”时,您实际上的意思是“一个线程被阻止”,因为那些是唯一可调度的实体,它们会占用CPU时间。当线程忙于等待时,它浪费了CPU时间。当线程被阻塞时,系统调用中的内核代码会看到数据或锁不立即可用,因此将线程标记为等待状态。然后,它跳转到调度程序,该调度程序将拾取另一个准备好执行的线程。阻塞系统调用中的此类代码可能如下所示:
100: if (data_available()) {
101: return;
102: } else {
103: jump_to_scheduler();
104: }
稍后重新安排线程上的线程,并在第100行重新启动,但它立即进入else分支并再次退出CPU。当数据可用时,系统调用最终返回。
不要一字不漏,这是基于我对操作系统的了解而做出的猜测,但您应该明白这一点。