11

我知道 Busy Waiting 的实现。这是一个这样的死循环:

//main thread
while (true) {
    msg = msgQueue.next();
    msg.runnable.run();
}

//....msg queue
public Message next() {
    while (true) {
        if (!queue.isEmpty()) {
            return queue.dequeue();
        }
    }
}

所以,“next()”方法看起来就像被阻塞了,实际上它一直在运行。这在书上被称为“忙着等待”。

什么是“进程被阻止”?它的实施细节如何?也是死循环吗?还是其他一些?像信号机制?

例如:猫 xxx | grep "abc"

进程“cat”读取文件并输出它们。

进程“grep”等待来自“cat”的输入。

所以在“cat”输出数据之前,“grep”应该被阻塞,等待输入并继续。关于这个“阻塞”的死亡循环一直在读取输入流的详细信息是什么?还是真的停止运行,等待信号唤醒它运行?

4

2 回答 2

16

区别基本上在于该过程会发生什么:

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

更新

可等待对象可以在操作系统级别以不同的方式实现,但通常它可能是硬件计时器、中断和由客户端代码向操作系统注册的可等待对象列表的组合。当中断发生时,操作系统的中断处理程序会被调用,该处理程序将扫描与该事件关联的任何可等待对象,并调用某些回调,该回调最终将向可等待对象发出信号(将它们置于信号状态)。这是一种过度简化,但如果您想了解更多信息,您可以阅读中断和硬件计时器。

于 2014-10-24T03:46:36.480 回答
0

当您说“进程被阻塞”时,实际上是指“线程被阻塞”,因为这些是唯一获得 CPU 时间的可调度实体。当线程忙于等待时,它会在循环中浪费 CPU 时间。当线程被阻塞时,系统调用中的内核代码发现数据或锁不是立即可用的,因此它将线程标记为等待。然后它跳转到调度程序,该调度程序选择另一个准备执行的线程。阻塞系统调用中的此类代码可能如下所示:

100:    if (data_available()) {
101:        return;
102:    } else {
103:        jump_to_scheduler();
104:    }

稍后线程被重新调度并在第 100 行重新启动,但它立即到达 else 分支并再次离开 CPU。当数据可用时,系统调用最终返回。

不要逐字逐句,这是我根据我对操作系统的了解的猜测,但你应该明白这一点。

于 2019-07-05T17:39:26.513 回答