死锁方案调研
- go vet : 无法输出死锁日志,只能做静态检查
- go -race: 无法输出死锁日志, 做一些并发安全的检查: 运行时检查
- pprof: 需要在代码中开启一个web服务端程序,运行时检测
- 引入第三方库:get github.com/sasha-s/go-deadlock: 把标准库的lock包装一层
推荐方案
- BuildTag="prod"替换成BuildTag="dev"
- 编译完跑自动化用例: 然后执行curl http://{ip}:8080/debug/pprof/goroutine?debug=1 -o pprof.log
- grep "runtime_SemacquireMutex" pprof.log, 有数据则有死锁可能性,否则没有死锁
- 有一定的误高率: 死锁的原理
死锁的模式
-
正常模式(Barging): 吞吐量大,性能强。 获取锁资源时, 如果协程获取不到锁首先会自旋4次,然后挂在一个等待队列中。 当锁释放的时候,会唤醒队列中的第一个协程,此协程会和其他新获取锁的协程一起竞争, 但是获取锁成功概率较大的是新协程,这样造成的问题 是队头协程容易饿死。
-
饥饿模式: 和正常模式不同的是:新获取锁的协程不会进入自旋状态, 而是排队。 这种模式比较公平, 但是性能不足
-
模式切换: 如果一个协程等待锁资源的时间超过1ms, 就切到饥饿模式, 等待队列为空或者等待时间少于1ms就可以切换到正常模式
参考资料:
- 死锁排查: blog.csdn.net/u013536232/…
- pprof检测死锁: blog.csdn.net/u013536232/…
- 锁(mutex)的一些使用注意事项: mozillazg.com/2019/04/not…
- 锁的实现模式和runtime_SemacquireMutex介绍: lailin.xyz/post/go-tra…
- go build tag使用: www.sunzhongwei.com/go-build-ta…