活锁:什么是活锁,示例,与死锁的区别

⚡ 智能摘要

活锁是一种并发情况,其中进程不断改变自身的状态以响应彼此,但却没有取得任何实际进展,它们保持活跃状态​​并消耗 CPU 周期,却永远不会完成其任务或被阻塞。

  • 🔁 定义: 活锁是指进程不断改变状态以适应彼此,但永远不会前进,这与死锁中进程被冻结的情况不同。
  • 🚶 计费示例: 两人步ping 在走廊里左右移动,互相让路,这象征着活锁,不断移动却永不交叉。
  • 🧮 原因: 由于进程表槽位有限,反复轮询和重试获取锁会导致进程进入活锁状态,而不会阻塞任何进程。
  • 比较: 死锁会冻结进程,饥饿会无限期地剥夺资源,而活锁会使进程一直处于忙碌状态,但无法取得任何进展。
  • 🛡️ 预防: 随机退避、重试限制和优先级排序打破了导致活锁的对称重试机制。
  • 🤖 人工智能视角: 机器学习会标记无进展的 CPU 模式,而 Copilot 可以帮助编写回退和锁排序代码,从而避免活锁。

活锁 Opera系统

什么是活锁?

A 活锁 这种情况是指,由于许多锁重叠,对独占锁的请求被反复拒绝。ping 共享锁之间不断相互干扰。进程不断改变其状态,导致它们无法完成任务。

活锁示例

例如1:

最简单的活锁效应例子是两个人面对面在走廊里相遇,两人都侧身让对方通过。他们左右移动,却始终无法前进,因为他们同时朝同一个方向移动。在这种情况下,他们永远不会真正相遇。

例如2:

活锁示例 Opera系统

在上图中,两个进程都需要两个资源,它们使用原始轮询方式来尝试获取所需的锁。如果一次尝试失败,该方法会再次尝试。

  1. 进程 A 持有资源 Y
  2. 进程 B 持有资源 X
  3. 过程 A 需要资源 X。
  4. 过程 B 需要资源 Y

假设进程 A 先运行并获取资源 X,然后进程 B 运行并获取资源 Y。无论哪个进程先运行,它们都无法取得进一步进展。

然而,这两个进程都没有被阻塞。它们反复占用CPU资源却没有任何进展,但从未因处理阻塞而停止。

因此,这种情况并非 僵局因为没有一个进程被阻塞;相反,我们面临着相当于死锁的情况,这被称为活锁。

什么导致活锁?

活锁与系统允许的进程数密切相关,而进程数又由进程表中的条目总数决定。因此,这些进程表槽位被视为有限资源。当进程反复尝试获取这些有限的资源,并且彼此不断让步时,所有进程都无法取得进展,系统便会进入活锁状态。

什么是死锁?

A 僵局 死锁是指操作系统中一个进程由于另一个等待进程占用所需资源而进入等待状态的情况。死锁是多处理中常见的问题,其中多个进程共享一种互斥的资源,这种情况被称为软锁或软件锁。

死锁示例

  • 现实世界中的例子就是单向行驶的交通。
  • 在这里,桥梁被视为一种资源。
  • 当发生死锁时,如果一辆车倒车(抢占资源并回滚),就可以很容易地解决死锁问题。
  • 如果出现死锁情况,可能需要几辆车倒车。
  • 因此,饥荒是有可能发生的。

死锁示例 Opera系统

死锁示例

什么是饥饿?

资源饥饿是指低优先级进程被阻塞而高优先级进程却能正常进行的情况。在任何系统中,对高优先级和低优先级资源的请求都会动态地发生。因此,需要制定某种策略来决定哪些资源优先得到服务以及何时提供服务。

某些算法会导致部分进程即使没有发生死锁也可能无法获得所需的服务。当某些线程长时间占用共享资源时,就会发生资源饥饿现象。

饥饿的例子

例如,某个对象提供了一个同步方法,该方法可能需要很长时间才能返回结果。如果一个线程频繁使用此方法,其他也需要频繁同步访问同一对象的线程往往会被阻塞。

死锁、饥饿和活锁之间的区别

  • 死锁是指操作系统中发生的一种情况,当一个进程因为所需的资源被另一个等待的进程占用而进入等待状态时,就会发生这种情况。
  • 另一方面,活锁与死锁几乎相同,只是活锁中涉及的进程的状态总是相互响应而不断变化,没有任何进程能够取得进展。
  • 所以,活锁是一种独特的资源匮乏案例。

常见问题

通过在重试过程中增加随机性或顺序性来减少活锁。相关技术包括重试前采用随机或指数退避策略、限制重试次数等。ping 重试次数,并强制执行固定的锁获取顺序,以防止进程互相镜像操作。

不。处于活锁状态的进程永远不会被阻塞——它们会持续运行,通过不断重试消耗 CPU 资源,但实际上却没有任何进展。而在死锁状态下,相关进程会停止并等待,因此不会占用 CPU 资源。

通常是的。死锁进程会处于冻结状态,很容易识别,而活锁进程则保持活动状态并不断改变状态。检测方法通常是观察CPU使用率是否很高,以及一段时间内进程是否没有任何进展。

竞态条件是指由于对共享数据的访问不同步而导致的错误或不可预测的结果。与之相反,活锁是指进程始终保持活动状态,并不断响应彼此而改变状态,但始终无法完成各自的工作。

是的。线程之间反复交互(例如,同时释放和重新请求锁)会导致活锁,但实际上并不会阻塞。这种情况经常出现在缺乏随机性的重试和退避逻辑中。

机器学习模型通过研究 CPU、调度和资源使用模式,标记出那些消耗大量资源却毫无进展的进程。这有助于运维人员在达到预设阈值之前更早地发现进程死锁,尤其是在涉及众多交互进程的大型云和数据中心工作负载中。

是的。GitHub Copilot 可以建议随机退避、超时和一致的锁顺序模式,从而降低活锁和死锁的风险。但开发者仍然需要仔细审查生成的并发逻辑,因为细微的时序错误很容易被忽略。

有时会发生这种情况。如果时序发生变化——例如,通过随机重试间隔——进程可能会打破这种模式并继续执行。如果没有这种变化,活锁可能会无限期地持续下去,浪费 CPU 资源,直到所有进程都无法完成其任务。

总结一下这篇文章: