Go死锁——当Channel遇上Mutex时

本文详细分析了在Go中使用带缓冲Channel和Mutex时可能导致的死锁问题,通过一个实际的案例展示了如何定位和解决这类死锁。通过分析goroutine堆栈和引入第三方库,揭示了在向带缓冲Channel写入数据时,如果没有正确处理可能的阻塞情况,将造成死锁。解决方案包括使用select语句进行非阻塞写入检查。
摘要由CSDN通过智能技术生成

🚀 优质资源分享 🚀

学习路线指引(点击解锁) 知识定位 人群定位
🧡 Python实战微信订餐小程序 🧡 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
💛Python量化交易实战💛 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

背景

用metux lock for循环,在for循环中又 向带缓冲的Channel 写数据时,千万要小心死锁!

最近,我在测试ws长链接网关,平均一个星期会遇到一次服务假死问题,因为并不是所有routine被阻塞,故runtime的检查无法触发,http health check又是另开的一个端口,k8s检查不到异常,无法重启服务。
 
 
经过一番排查论证之后,确定了是 **混用带缓冲的Channel和Metux造成的死锁 (具体在文末总结)**问题,请看下面详细介绍。

死锁现象

我们使用了gin框架,预先接入了pprof封装组件,这样通过http(非生产)就能很方便的查看go runtime的一些信息。
 
果不其然,我们打开后发现了大量的 goroutine泄漏

点开 full goroutiine stack dump,可以看到有很多死锁等待,导致goroutine被阻塞:

其中:

  • semacquire阻塞:有9261/2 个 routine
  • chan send阻塞:有9处

问题出在哪里?

启发

有一个作者:https://wavded.com/post/golang-deadlockish/ 分享了一个类似的问题。
下面是引用的部分正文内容。

1)Wait your turn
在我们为应用程序提供的一项支持服务中,每个组都有自己的Room,可以这么说。我们在向房间广播消息之前锁定了members列表,以避免任何数据竞争或可能的崩溃。像这样:

?

| 123456789 | func (r *Room) Broadcast(msg string) {``r.membersMx.RLock()``defer r.membersMx.RUnlock()``for _, m := range r.members {``if err := s.Send(msg); err != nil {

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值