Windbg程序调试系列3-线程阻塞问题

Windbg程序调试系列2-内存泄露问题

本篇我们继续跟大家分享,如何分析解决线程阻塞问题。

从根本上讲,线程阻塞属于程序Hang的一种,其表现主要有:

1. 随着请求的增加,线程数一直增加,可能会把线程池打爆

2. 低CPU使用率(被阻塞后的CPU使用率降低)

3. 请求没有返回,客户端一直在等待,直至Timeout。

 那么,从线程状态上看,什么是阻塞? 一个线程经历的5个状态,创建,就绪,运行,阻塞,终止。各个状态的转换条件如下图:

Windbg程序调试系列3-线程阻塞问题

上图中有个阻塞状态,就是说当线程中调用某个函数,需要IO请求,或者暂时得不到竞争资源的,操作系统会把该线程阻塞起来,避免浪费CPU资源,等到得到了资源,再变成就绪状态,等待CPU调度运行。

线程发生阻塞的现象就是,进程的线程数会越来越多!

线程阻塞问题的分析思路:

持续请求过程中,抓两个或者三个Dump,看线程增加的速度,每次抓Dump间隔30s或者1分钟
对比的看每个Dump中:

Windbg程序调试系列3-线程阻塞问题

线程池的大小 !threadpool

线程的分类和状态 !threads

查看线程阻塞 !syncblk

查看阻塞线程的根源线程、线程请求的资源对象 、被阻塞的线程数

查看阻塞根源线程的堆栈~Xs !clrstack

分析线程阻塞的原因,改进代码

1. 查看线程池的大小:!threadpool,有时间间隔两个Dump对比着看,看线程池的线程数的增长情况:

Windbg程序调试系列3-线程阻塞问题

2. 查看线程的分类和线程的状态 !threads,从下图可以看出,后台线程一直在增加

Windbg程序调试系列3-线程阻塞问题

3. 查看线程阻塞  !syncblk,也是看这两个dump,对比着看

Windbg程序调试系列3-线程阻塞问题

我们发现:

第一个Dump中95号线程 阻塞了(1021-1)/2=510个线程
第二个Dump中79号线程 阻塞了(1099-1)/2=549个线程

95号线程独占的对象资源 00000026ba7c4dc0 (System.Object)

79号线程独占的对象资源也是00000026ba7c4dc0(System.Object)

两个线程同时锁住了同一个资源!00000026ba7c4dc0(System.Object)

此时,线程阻塞问题已经确定,接下来,我们要重点分析阻塞的根源线程(持有什么资源不释放,导致其他线程在等待),95号线程、79号线程

4. 查看阻塞线程的根源线程、线程请求的资源对象 、被阻塞的线程数

例如 95号线程:

1 查看阻塞根源线程的堆栈 2 ~95s 3 !clrstack

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjwsx.html