✅什么是活锁,和死锁有什么区别?

✅什么是活锁,和死锁有什么区别?

典型回答

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

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

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

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

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

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

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

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

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

✅CAS一定有自旋吗?

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

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