dump常用命令及数据分析

1.        ~*e !CLRStack -a
•        目的:查看所有托管线程的托管/本机调用栈,找出线程都卡在什么方法上(例如 .Result/.Wait()、长时间的 DB/网络调用、等待锁)。
2.        !syncblk
•        目的:列出被锁(Monitor/lock)对象和等待线程,确认是否存在单点锁竞争或死锁。
3.        !dumpheap -type System.Web.HttpContext (或 !dumpheap -type HttpContext)然后对若干 HttpContext 地址运行 !gcroot <addr>
•        目的:确认是否存在未释放的请求上下文导致请求积压或内存保留。
4.        !dumpheap -type System.Threading.Tasks.Task 并对可疑 Task 做 !gcroot
•        目的:查找大量未完成或被阻塞的 Task/TaskCompletionSource 引用链(异步未完成导致泄漏/阻塞)。
5.        !threadpool 或 !tp(若你的 SOS 版本支持)和 !runaway
•        目的:查看线程池队列/线程使用情况及各线程的 CPU 消耗。
6.        可选:~*k(所有线程本机栈)与 !analyze -v(如果尚未运行)。

~83s // 切换到线程 83(Thread ID:83)

!clrstack // 查看托管调用栈,定位具体业务代码(如命名空间、类名、方法名)

!dumpstack // 查看完整栈(含非托管),排除底层组件问题

!pe // 若存在异常,查看未处理异常信息

 

!syncblk命令结果数据分析

索引     同步块地址    锁持有/等待数  重入次数  锁持有者地址  系统线程ID  托管线程ID  锁对象地址      锁对象类型
-----------------------------------------------------------------------------------------------------------
85      02cb632c      5              1         02c09760     509c       117        0e3fd18c      System.Object
90      02cb6228      488            0         00000000     none       none       213b68c4      System.Threading.TimerQueue
303     55cfbe50      43             1         400231e8     4758       237        0d3a85b8      System.Object

-----------------------------
Total           317    // 总同步块数量
CCW             4      // COM 互用包装
RCW             5      // 运行时调用包装
ComClassFactory 0
Free            97     // 空闲同步块

二、每一列标准解析(官方定义)

表格
 
列名含义
Index 同步块唯一编号
SyncBlock 同步块内存地址
MonitorHeld 锁总计数 = 持有数 + 等待数
Recursion 同一个线程重复加锁次数(重入)
Owning Thread 持有锁的线程地址(0 = 无持有者)
Thread ID 系统线程 ID(十六进制)
Managed ID 托管线程 ID
SyncBlock Owner 被加锁的对象(内存地址 + 类型)
 

 

三、逐行极简解析

行 1:Index=85

  • 锁对象:System.Object(代码里的 lock 对象)
  • MonitorHeld=5:1 个线程持有锁,4 个线程在等待
  • 持有者:线程 509c(托管 117)
  • 状态:轻度锁竞争

行 2:Index=90 【最严重】

  • 锁对象:.NET 内置定时器队列 TimerQueue
  • MonitorHeld=488:488 个线程 / 定时器在等待这个锁
  • 持有者:none(无线程持有锁,但有大量等待)
  • 结论:定时器严重堆积、线程池耗尽、Timer 完全阻塞

行 3:Index=303

  • 锁对象:System.Object
  • MonitorHeld=43:1 个线程持有,42 个线程等待
  • 持有者:线程 4758(托管 237)
  • 状态:重度锁竞争

四、总结(一句话)

  • 无死锁
  • Timer 队列堆积 488 次(高危)
  • 两个业务锁存在严重线程争抢
  • 程序表现:卡顿、响应慢、定时任务不执行、线程池耗尽

最终结论

你的程序不是死锁,而是:
  1. Timer 定时器严重阻塞 / 堆积
  2. 两处锁竞争严重
  3. 线程池资源耗尽
posted @ 2026-03-11 19:36  无聊的蚂蚁  阅读(18)  评论(0)    收藏  举报