📰 来源: 博客园
一、第一步:宏观看整体指标 !tp
二、第二步:排查托管锁 !syncblk
MonitorHeld=占用数、有无等待的Waiter线程三、第三步:抽卡死线程栈(从syncblk里提取OS-TID)
~~[0xTID]s;!clrstack 打印单个卡死线程托管堆栈:
ManualResetEventSlim.Wait → Task.InternalWait → Task.Wait()→ 锁定:同步
.Wait()阻塞异步任务,上下文死锁。四、第四步:结合代码解释「偶发正常、随机卡死」
GetAsync同步执行完毕,返回已完成Task,await不放线程,全链路顺行,正常释放;await释放工作线程;IO完成回调要切回AspNetSynchronizationContext,但主线程被.Wait()占死 → 闭环死锁、线程永久滞留。五、第五步:区分两种死锁、落地修复
.Wait()/Result + await无ConfigureAwait(false)修复二选一:
- 方案1:全链路改成async/await,删除所有
.Wait(); - 方案2:所有
await xxx.ConfigureAwait(false),切断回调绑定请求上下文。
.Wait();await xxx.ConfigureAwait(false),切断回调绑定请求上下文。!tp看池子满不满,!syncblk辨锁死还是卡死,切线程栈找Wait,缓存决定偶发好坏
🔗 原文链接: 点击阅读原文
文章评论