641 字
3 分钟
活锁、饥饿和死锁有什么区别
死锁是参与者互相等待,相关执行流都无法前进;活锁是执行流仍在运行、不断响应或重试,但反复让步导致没有实际工作完成;饥饿是某个执行者长期得不到所需 CPU、锁或资源,其他执行者可能继续取得进展。
例如两个人在走廊相遇,每次都同时向同一侧让路,又同时改向,双方一直动作却无法通过,这是活锁。若两个线程分别持有一把锁并等待对方释放,则是死锁。若一个低优先级线程始终被高优先级任务压住,它可能饥饿,但系统整体仍有进展。
活锁常见于冲突后立即同步重试的算法。加入随机或指数退避、打散重试时间、限制重试次数,或引入仲裁者,可以降低双方持续碰撞的概率。饥饿可通过公平队列、优先级老化、配额或有界等待缓解;但公平策略也可能牺牲吞吐量,且公平的定义要明确到请求顺序、时间上界或资源比例。
例如多个客户端同时抢同一资源失败后又在固定间隔重试,可能长期同步碰撞;退避加随机抖动可以打散重试节奏。分析饥饿则要看请求是否持续排在队尾以及是否存在公平性保证。
这三个概念不能仅看 CPU 是否繁忙来判断。活锁时 CPU 可能很忙,却没有有效进展;死锁时也可能存在无关线程继续运行;饥饿则关注某个请求者长期被排除。工程排查应同时观察等待依赖图、请求成功率、队列位置和有效工作完成量。
常见追问
Q:死锁和饥饿都在等待,怎么区分?
A:死锁是一组执行者构成循环依赖且都不能推进;饥饿是个别执行者一直得不到资源,系统其他部分仍可运行。
Q:活锁是不是没有锁?
A:不一定。活锁可以发生在带锁或无锁协议中;其特征是持续改变状态或重试,但始终未完成目标。
Q:随机退避能保证不再活锁吗?
A:不能绝对保证,只能降低同步碰撞概率。需要确定性保证时,应采用仲裁、公平排队、有限重试后升级处理等机制。
目录