据我了解:
- 活锁:一个线程无法取得进展,但它会永远执行(该线程无限期地处于活动状态):例如,它处于一个循环中,无限地尝试访问永远不会再可用的共享资源。
- 死锁:线程没有进展,但甚至没有执行(线程无限期休眠,因此已死亡):它正在等待操作系统根据永远不会发生的条件唤醒它。
- 饥饿:一个线程没有取得进展并且被阻塞(类似于死锁),但是等待被唤醒的条件确实发生了,只是碰巧有其他线程总是在我之前取代我的位置。
首先,这些定义是否正确?如果正确,它们是否也适用于单线程程序?例如:
// begin of useful work
until (some_buggy_condition_that_will_never_be_satisfied())
do_something();
// end of useful work
在上面的例子中,循环将永远执行,因为与共享资源无关的条件有一个错误,并且永远不会满足。因此线程:
- 正在执行。
- 为了做有用的工作,循环必须结束
- 循环永远不会结束,因为结束条件永远不会满足
因此,该列表符合我上面的活锁定义,只是我在并发上下文之外使用了该术语。这样可以吗?
需要多个线程才能获得实时锁定。当交互线程系统不断重复某种备份和重试行为而不是执行任何工作时,我们称其为“实时锁定”。想象一个门口,想象两个或多个卑躬屈膝的绅士都想同时通过。但他们所做的只是轮流说:“不!我坚持要你先走。 ”然后,没有人会通过那扇门。
无限循环不是实时锁定。许多程序中的线程都会无限循环地执行有用的工作。我们只在没有任何工作执行时才说“实时锁定”。
需要多个线程才能发生死锁。当一组线程中任何一个线程在获取该组中其他成员所持有的资源之前都无法执行任何操作时,我们称其为“死锁”。想象一座单车道桥,两边都有一队车辆想要通过,但每队前面的咄咄逼人的司机都在互相喊叫:“除非你们让开,否则我不会移动一英寸。”
饥饿有点像半个活锁。它有相同的后退和重试的持续循环,不同之处在于该循环允许至少一个线程取得进展,同时阻止至少一个其他线程。想象一个胆小的人害怕推门而入,因为另一边似乎有无数人从门前走过。
更新你问过,
在我看来,在谈论单线程程序时,没有理由使用任何这些术语。如果你这样做,只会让人感到困惑。
就我个人而言,我会将其称为具有错误退出条件的循环。
注意! 当线程试图获取已经持有一个锁的资源上的第二个锁时,有些作者会使用短语“自死锁” 。但是,如果您谈论的是单线程程序,那么为什么线程会挂起锁呢?
是的,在并发上下文之外使用术语“活锁”是可以的,只要您意识到区别并在正确的上下文中澄清它。
虽然传统上活锁是指多线程环境中两个或多个线程正在积极执行但由于相互干扰而无法取得进展的情况,但这个概念可以在单线程场景中松散地应用,但有一些注意事项。
在您的例子中,您描述的是一个无限循环,其中线程由于错误情况而不断执行而没有取得任何进展。这类似于活锁,因为系统虽然活着,但“卡住了”,没有取得任何有用的进展。