Linux多线程死锁是怎样发生的?排查时为什么先看线程栈和锁顺序?

浏览量:3
时间: 2026-10-30 11:54:07

CONCURRENCY · 线程同步

这是Linux/C++嵌入式面试的经典题,既考并发基础,也能检验真实调试方法。

先给结论

常见死锁是线程持有部分资源后相互等待,形成环形依赖。排查要明确谁持有哪把锁、谁在等待什么,再统一锁顺序或缩小锁粒度。

① 面试官到底在考什么?

很多程序偶发卡住,CPU占用却不一定很高。与忙循环不同,死锁线程可能都阻塞在互斥锁等待上,日志也可能停在特定位置。

公开的死锁资源等待关系图,用来读出“线程A持有锁1等锁2、线程B持有锁2等锁1”的循环等待。图是工程关系示意,不是某个项目的真实故障截图。

② 工程思路:按这个顺序展开

01 / 先定位卡住的线程

保留进程ID、线程信息与故障时刻,用gdb的thread apply all bt、/proc及日志查看各线程停在哪个等待点。

02 / 还原持锁和等待关系

画出线程—锁之间的依赖,重点检查是否存在A先拿锁1后拿锁2、B却反着拿锁的情况。也检查遗漏解锁、异常路径及自锁。

03 / 修复要防复发

统一全局加锁顺序,尽量缩短临界区,避免持锁调用不受控的外部接口;需要时采用trylock/超时和结构化锁管理,但超时不是消除设计问题的替代品。

③ 常见失分点

  • 一看到线程卡住就说“肯定死锁”,没有排除I/O阻塞和等待条件未满足

  • 认为改成递归锁就能彻底解决所有死锁

  • 只在线上增加打印,却没有保存线程栈和复现场景

④ 面试时可以这样回答

“我先把问题区分为CPU忙循环、I/O阻塞和锁等待。如果怀疑死锁,就抓所有线程栈,找互斥锁等待链并还原持锁顺序。修复一般是统一锁顺序、减少嵌套持锁,随后用压力与并发场景回归。”

面试官可能继续追问

如果只有一个线程,它还可能因为锁而把自己卡住吗?


声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。仅供学习交流使用,不构成商业目的。版权归原作者所有,如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时删除。侵权投诉
相关推荐HOT
开班信息