Skip to content

面试速答(先看这里)

**一句话结论:**一般来说,会发生活锁的原因,主要是 过度协作或不当的重试策略导致线程相互“礼让”或“退让” ,结果谁也无法获得执行关键操作所需的稳定条件。

60秒标准回答:

死锁指的是两个或多个线程因为互相等待对方释放资源而卡住,程序无法继续执行

而 活锁 ,指的是 两个或多个线程 在持续运行并改变状态 ,但它们的工作 无法取得任何实质性进展 。线程没有被阻塞,而是在不断地响应对方的状态变化,陷入一种无意义的“忙等待”循环

一般来说,会发生活锁的原因,主要是 过度协作或不当的重试策略导致线程相互“礼让”或“退让” ,结果谁也无法获得执行关键操作所需的稳定条件。就像 两个人过在独木桥相遇

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**死锁指的是两个或多个线程因为互相等待对方释放资源而卡住,程序无法继续执行。
  • **要点2:**而 活锁 ,指的是 两个或多个线程 在持续运行并改变状态 ,但它们的工作 无法取得任何实质性进展 。
  • **要点3:**发生活锁后,虽然程序没有“卡死”,相关线程仍在消耗 CPU 资源(因为它们还在执行代码)。
  • **要点4:**CAS自旋是:每个人都不断尝试快速挤过桥(执行CAS),如果发现桥被堵住了(CAS失败),就等一会再尝试挤过去。
  • **要点5:**想要避免活锁的发生,可以从以下几个方面入手:

**记忆锚点:**CAS → 无法取得任何实质性进展 → 指的是两个或多个线程 → 过度协作或不当的重试 → 避免过度协作/礼让 → 实这种最多是像活锁

关键取舍:

  • 死锁指的是两个或多个线程因为互相等待对方释放资源而卡住,程序无法继续执行。
  • 发生活锁后,虽然程序没有“卡死”,相关线程仍在消耗 CPU 资源(因为它们还在执行代码)。
  • 限制重试次数: 设置最大重试次数,超过后采取不同策略。

易错提醒:

  • CAS自旋是:每个人都不断尝试快速挤过桥(执行CAS),如果发现桥被堵住了(CAS失败),就等一会再尝试挤过去。
  • 想要避免活锁的发生,可以从以下几个方面入手: 引入随机性: 在重试前增加 随机退避时间 ,显著降低重试动作同步发生的概率。

加分表达:

  • 一般来说,会发生活锁的原因,主要是 过度协作或不当的重试策略导致线程相互“礼让”或“退让” ,结果谁也无法获得执行关键操作所需的稳定条件。

追问准备:

  • 围绕「CAS」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「无法取得任何实质性进展」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「指的是两个或多个线程」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

📄 ✅什么是死锁,如何解决?

打开文档:✅什么是死锁,如何解决?

死锁指的是两个或多个线程因为互相等待对方释放资源而卡住,程序无法继续执行。

而活锁,指的是两个或多个线程在持续运行并改变状态,但它们的工作无法取得任何实质性进展。线程没有被阻塞,而是在不断地响应对方的状态变化,陷入一种无意义的“忙等待”循环。

一般来说,会发生活锁的原因,主要是过度协作或不当的重试策略导致线程相互“礼让”或“退让”,结果谁也无法获得执行关键操作所需的稳定条件。就像两个人过在独木桥相遇:

  • A 和 B 迎面走来,A 说“你先走”,B 说“你先走”;
  • 双方都后退一步;
  • 然后又同时前进,又撞到;
  • 然后又同时后退……反复循环,永远过不了桥。

发生活锁后,虽然程序没有“卡死”,相关线程仍在消耗 CPU 资源(因为它们还在执行代码)。表面上有活动(日志可能显示线程在重试、回退、响应),但整体任务无进展。

很多人看到这里,会认为CAS的自旋是活锁。但是其实这种最多是像活锁,但是他不是一种活锁。因为我们前面说过,活锁主要是因为过度协作导致的礼让。

活锁是:A看到B过来就让开,B看到A让开也想让A先走,结果两人在门口一直让路谁也过不去(协作逻辑导致僵局)。

CAS自旋是:每个人都不断尝试快速挤过桥(执行CAS),如果发现桥被堵住了(CAS失败),就等一会再尝试挤过去。虽然大家挤来挤去可能暂时都过不去,但每个人都在尝试相同的“挤”的动作,没有互相让路的协作逻辑。

📄 ✅CAS一定有自旋吗?

打开文档:✅CAS一定有自旋吗?

想要避免活锁的发生,可以从以下几个方面入手:

  • 引入随机性: 在重试前增加随机退避时间,显著降低重试动作同步发生的概率。
  • 避免过度协作/礼让: 设计线程行为时,不要让它们完全依赖对方的状态来决定自己的每一步动作。有时需要让某个线程“坚持”一段时间。
  • 优先级或顺序: 为线程分配优先级或固定顺序,打破对称性。
  • 限制重试次数: 设置最大重试次数,超过后采取不同策略。