GO语言基础教程(154)Go死锁:Go死锁解密:当你的代码陷入“互相等待“的尴尬局面

在Go语言并发编程中,死锁就像一个两个人都想先过的狭窄门洞 - 你不让我,我不让你,最后谁都过不去。今天,就让我们一起揭开这个让无数Go开发者头疼的难题。

死锁到底是什么?一个生活化的比喻

想象你和朋友去餐厅吃饭,需要"筷子+勺子"才能用餐。你手里握着唯一的筷子(持有资源),等着朋友的勺子(等待资源);朋友手里握着唯一的勺子(持有资源),等着你的筷子(等待资源)。两人都不释放自己的资源,最终谁也吃不上饭——这就是死锁。

对应到Go程序中:

  • "你和朋友" = 多个goroutine
  • "筷子/勺子" = 程序资源(如锁、通道、文件句柄)
  • "互相等待" = goroutine间的资源依赖循环

死锁的核心特征很明显:程序卡住无任何推进,日志无输出(或卡在某个步骤),CPU和内存占用极低(goroutine都在等待,无实际工作)。

死锁的四个必要条件:少一个都不会发生

死锁并非随机出现,它必须同时满足4个经典条件。只要破坏其中任意一个条件,死锁就不会发生。

条件一:互斥条件 —— 资源只能"独占使用"

某个资源同一时间只能被一个goroutine占用,其他goroutine要使用,必须等待当前占用者释放。

就像厕所隔间一次只能容纳一人,Go中的sync.Mutex(互斥锁)是典型的"互斥资源"——一个goroutine加锁后,其他goroutine必须等待其解锁才能再次加锁。

条件二:持有并等待条件 —— 拿着资源等其他资源

一个goroutine已持有至少一个资源,仍在等待其他goroutine持有的资源,且不释放自己已持有的资源

回到餐厅例子:你握着筷子(已持有资源),还在等朋友的勺子(等待资源),且不把筷子交给朋友——这就是"持有并等待"。

条件三:不可剥夺条件 —— 资源不能"强行抢走"

一个goroutine持有的资源,不能被其他goroutine强行剥夺,只能由持有方主动释放。

比如你握着筷子,别人不能直接从你手中抢走,只能等你主动放下;Go中的互斥锁也遵循此规则。

条件四:循环等待条件 —— 互相等待对方的资源

多个goroutine形成闭环,每个goroutine都在等待下一个goroutine持有的资源。

例如:goroutineA持有资源1、等资源2;goroutineB持有资源2、等资源1——两者形成循环,永远无法获取所需资源。

Go死锁经典场景:附完整代码示例

了解了死锁的原理,让我们看几个Go中最常见的死锁场景,以及它们的完整代码示例。

场景一:无缓冲通道的同步死锁

package main

import "fmt"

func main() {
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

值引力

持续创作,多谢支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值