Linux高并发死锁排查需主动监控锁依赖、识别循环等待链,分层使用lockdep、/proc/pid/stack、gdb、pstack及perf等工具实现早发现、准定位、快验证。

排查 Linux 高并发下的资源竞争死锁,核心不是“等它卡住再看”,而是主动监控锁依赖关系、识别循环等待链,并结合内核与用户态工具分层定位。关键在于早发现、准定位、快验证。
看内核是否开启死锁检测(lockdep)
Linux 内核自带 lockdep 框架,能实时跟踪所有锁的获取/释放顺序,自动检测潜在死锁环。但它默认可能未启用——尤其在生产内核中为性能常被关闭。
- 检查是否启用:
cat /proc/sys/kernel/lockdep,输出1表示已开;0表示关闭 - 临时开启(需 root):
echo 1 > /proc/sys/kernel/lockdep(仅限调试环境,重启失效) - 永久启用:编译内核时配置
CONFIG_LOCKDEP=y,或启动参数加initcall_debug lockdep=1 - 触发后,内核日志(
dmesg)会打印完整锁依赖图和死锁路径,例如 “possible recursive locking detected” 或 “circular locking dependency”
抓取进程级锁状态与阻塞链
当怀疑某个服务僵死,先确认是否真为死锁(而非单纯高负载或 IO 等待),再聚焦锁持有关系。
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 用
ps -eo pid,comm,wchan:20,state,stack | grep 'D\|UN'找出处于不可中断睡眠(D 或 UN)状态的进程,它们通常卡在锁或驱动上 - 对可疑 PID,查其调用栈:
cat /proc/<pid>/stack</pid>,重点看是否停在mutex_lock_slowpath、down(信号量)、__wait_event等同步原语 - 结合
/proc/<pid>/status</pid>中的LockedPages、voluntary_ctxt_switches和nonvoluntary_ctxt_switches判断是否因锁争抢导致频繁上下文切换
分析用户态应用的锁竞争(以 pthread 为例)
很多死锁发生在用户空间线程间,比如多线程服务中互斥锁嵌套顺序不一致。
- 用
gdb -p <pid></pid>进入进程,执行info threads和thread apply all bt查所有线程堆栈,找多个线程都卡在pthread_mutex_lock且锁地址不同但相互等待 - 配合
pstack <pid></pid>快速输出线程栈(无需 gdb),比对各线程持有哪些锁、正在申请哪把锁 - 若使用 glibc 2.30+,可启用
libpthread的锁调试支持:启动前设环境变量MALLOC_CHECK_=2和LD_PRELOAD=/lib64/libpthread.so.0(部分版本支持锁统计)
用 perf 追踪锁事件与热点路径
perf 不仅能看 CPU 占用,还能采样锁相关事件,暴露真实竞争点。
- 记录锁获取耗时:
perf record -e sched:sched_stat_sleep,sched:sched_stat_blocked -g -p <pid></pid>,然后perf report查哪些函数长时间处于 blocked 状态 - 统计锁争用:
perf record -e lock:lock_acquired,lock:lock_contended -a sleep 10,再用perf script分析哪些锁被频繁 contended - 结合
perf probe在关键锁函数(如mutex_lock)插桩,观察调用上下文与参数,确认锁 ID 和持有者

















