当前位置: GO > 使用 pprof 排查 Go 死锁的步骤

使用 pprof 排查 Go 死锁的步骤

2025-05-22 分类:GO 作者:admin 阅读(20)

死锁(Deadlock)的简明定义

死锁是指多个进程(或线程、协程)在竞争资源时,因互相持有对方所需的资源且不释放,导致所有参与者无限阻塞的状态。


死锁的四个必要条件

  1. 互斥条件:资源一次只能被一个进程占用(如锁、文件句柄)。

  2. 占有并等待:进程持有至少一个资源,同时等待其他被占用的资源。

  3. 非抢占条件:已分配给进程的资源不能被强制剥夺,只能主动释放。

  4. 循环等待:多个进程形成环形依赖链(如A等B,B等C,C等A)。

👉 只有这四个条件同时满足时,死锁才会发生。

Go语言中的死锁示例

1,显式死锁直接崩溃

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select (no cases)]:
main.main()
/home/hezichao/go_project/test/go_test/prop/deadlock/deadlock.go:29 +0x2b

2,真实场景示例:局部死锁导致性能下降(不崩溃)(代码暂未模拟出)

场景描述

假设有一个 电商订单系统,用户支付成功后,系统需要:

  1. 扣减库存inventory_service)。

  2. 生成物流单shipping_service)。

  3. 更新订单状态order_service)。

由于服务间存在依赖关系,高并发时可能发生局部死锁,表现为:

  • 部分订单卡在“处理中”状态(但系统整体仍可响应新请求)。

  • API 延迟飙升(从 100ms 增加到 10s+)。

  • 数据库连接池耗尽(因长时间持有事务锁)。

如何避免死锁?

  1. 破坏占有并等待:一次性申请所有所需资源(如全局锁)。

  2. 破坏非抢占:使用超时机制(如TryLockcontext.WithTimeout)。

  3. 破坏循环等待:统一资源获取顺序(如总是先锁A再锁B)。

  4. 工具检测

    • Go的-race flag检测数据竞争(可能引发死锁)。

    • 使用pprof分析阻塞的Goroutine。

死锁是多个执行单元因资源竞争陷入的永久阻塞状态,需通过设计规范或工具预防。


使用 pprof 排查 Go 死锁的步骤

1. 复现死锁问题

确保程序能触发死锁(如卡死、CPU 占用 0% 但未退出)。

2. 采集 Goroutine 阻塞数据

方式 1:HTTP 服务集成(推荐)

访问 http://localhost:6060/debug/pprof/goroutine?debug=2 查看所有 Goroutine 堆栈。

方式 2:程序崩溃时保存快照

在怀疑死锁处调用此函数(如收到 SIGUSR1 信号时)。

3. 分析阻塞的 Goroutine

关键观察

  • 查找大量 Goroutine 卡在 sync.Mutex.Lock() 或 chan send/receive

  • 检查是否形成循环等待链(如 A 等 B,B 等 C,C 等 A)。

示例输出分析

4. 结合其他 Profile 确认

Mutex 竞争分析(需代码插桩):

Block 阻塞分析

5. 解决死锁的常见手段

  1. 按固定顺序获取锁(破坏循环等待):

    2.使用 select + 超时(破坏非抢占):


    3.减少锁粒度(如用 sync.Map 或原子操作替代)。

     6.验证修复

    • 用 go run -race main.go 检测数据竞争。

    • 压力测试观察是否再次卡死。

     

通过 pprof 快速定位阻塞的 Goroutine 和资源依赖链,是解决死锁的最高效方法。

死锁、goruntine阻塞、channel阻塞有什么区别和联系

  • 区别

    • 死锁 是一种特定的阻塞状态,通常涉及多个 goroutine 和锁的相互等待。
    • goroutine 阻塞 是一个更广泛的概念,指任何导致 goroutine 无法继续执行的状态。
    • channel 阻塞 是 goroutine 阻塞的一种特定情况,特指在使用 channel 进行通信时的阻塞。
  • 联系

    • 死锁是 goroutine 阻塞的一种形式,但并不是所有的 goroutine 阻塞都是死锁。
    • channel 阻塞是 goroutine 阻塞的一个常见场景,但它可以是正常的、预期的行为,而非错误。

「三年博客,如果觉得我的文章对您有用,请帮助本站成长」

赞(0) 打赏

支付宝
微信
0

支付宝
微信
标签:

上一篇:

下一篇:

你可能感兴趣

共有 0 - 使用 pprof 排查 Go 死锁的步骤

博客简介

精彩评论

  • admin(6年前 (2020-03-09))

    分别用不同厚度的筏板定义,画图后这设置筏板变截面处理。 http://f.fwxgx.co...

    评:新文章!
  • admin(6年前 (2020-03-09))

    分别用不同厚度的筏板定义,画图后这设置筏板变截面处理。 http://f.fwxgx.co...

    评:新文章!
  • admin(6年前 (2020-03-09))

    新增一个框架图! http://biji.jinli.vip/wp-content/upl...

    评:新文章!
  • 一位WordPress评论者(6年前 (2020-02-13))

    嗨,这是一条评论。 要开始审核、编辑及删除评论,请访问仪表盘的“评论”页面。 评论者头像来自...

    评:世界,您好!