47

在多任务系统中,一些异常情况会阻止执行进程或线程的进程。我将把进程和线程都简称为“进程”。其中两种情况称为死锁和活锁。

前者指的是相互阻塞的进程,从而阻止任何一个执行。后者指的是相互阻止进程的进程,但实际上并不阻止执行。例如,它们可能会不断地导致彼此回滚事务,但都无法完成它们。

另一种情况被称为资源匮乏,其中进程进行所需的一个或多个有限资源已被它们耗尽,除非进程继续,否则无法恢复。这也是活锁的一个特例。

我想知道“饥饿”是否有任何其他定义,尤其是学术定义,不仅限于“资源匮乏”。特别欢迎参考。

而且,不,这不是家庭作业。:-)

4

6 回答 6

98

想象一下,你在一家餐馆排队购买食物,孕妇优先购买。而且总是有一大群孕妇来。

你很快就会饿死。;)

现在想象你是一个低优先级的过程,而孕妇是高优先级的。=)

于 2009-07-22T01:30:11.707 回答
36

我不会说资源匮乏是活锁的特例。通常:

  • 在活锁中,没有线程取得进展,但它们继续执行。(在死锁中,他们甚至不继续执行)

  • 饥饿时,一些线程确实取得了进展,而一些线程没有执行。

一个很好的解释:http ://docs.oracle.com/javase/tutorial/essential/concurrency/starvelive.html 。但我知道术语的选择可能会有所不同。

说到饥饿,我听到的定义是:

假设可以指定与假设(信号量语义、操作系统调度程序行为...)一致的无限执行路径(交错),使得线程 T 暂停等待某些资源并且永远不会恢复,即使它可能无限多次. 那么T被称为饥饿。

但实践与此不符。假设两个线程在一个无限循环中执行相同的临界区。您的同步代码允许第一个线程每小时进入临界区一次。是饿死了吗?两个线程都被允许进行,但第一个线程正在痛苦地缓慢地完成它的工作。

最简单的饥饿源是弱信号量。如果您使用行为相似的同步原语(或构建您自己的),则会导致饥饿。

饥饿是众所周知的经典问题:

欲了解更多详情,我衷心推荐 The Little Book of Semaphores(免费):http ://www.greenteapress.com/semaphores/ 。

您在问是否每次饥饿都是由于等待某些资源引起的。我会说——是的。

一个线程可以被挂起:

(1) 在某些阻塞系统调用上 - 等待/获取互斥锁、信号量、条件变量;写(),轮询()等。

(2) 在一些非阻塞操作上——比如执行计算。

饿死 (1) 就是饿死资源(互斥体、缓冲区等)。

饿死 (2) 就是饿死 CPU - 您可以将其视为资源。如果发生这种情况,则问题出在调度程序上。

高温高压

于 2009-07-22T02:52:54.690 回答
12

通常会出现饥饿或“无限期阻塞”的另一个领域是在谈论优先级调度算法时。优先级调度算法有可能让一些低优先级进程无限期地等待。稳定的高优先级进程流可以阻止低优先级进程运行。

对于优先级调度程序,解决方案是“老化”。老化是逐渐增加在系统中等待很长时间的进程的优先级的技术。

于 2009-07-22T01:35:27.237 回答
7

饥饿只是当一个进程或服务没有被服务时,即使系统上没有死锁。

这是我只是为了澄清目的而编造的一个例子。

想象一个控制计算机访问 WAN 或类似事物的算法。这个算法可能有一个策略,上面写着“为那些将使用较少带宽的计算机提供优先访问权。”,这似乎是一个正确的策略,但是当单台计算机想要访问网络进行 ftp 上传时会发生什么在某处发送几 GB。仅使用此策略,该计算机将饿死,因为该算法永远不会选择该计算机,因为总会有其他计算机请求更小的带宽使用。

那叫饿死。

于 2009-07-22T01:37:48.793 回答
1

工作也是一种资源。当生产者-消费者设置中的工作分配不公平(或不理想)时,某些线程可能无法获得足够的工作项来让它们一直忙碌。

于 2009-07-22T01:29:56.027 回答
0

一个进程在较长时间内没有获得一个或多个资源。这不是死锁,因为一个进程运行没有问题。可以使用老化来解决这个问题,每个请求都使用一个老化因子。

于 2015-07-12T06:16:41.180 回答