0

0

Go并发编程为什么会阻塞_Go阻塞原因与解决思路

P粉602998670

P粉602998670

发布时间:2026-01-16 09:54:02

|

466人浏览过

|

来源于php中文网

原创

向无缓冲 channel 发送数据时若无接收协程,会永久阻塞并触发死锁 panic;常见原因包括未启动接收 goroutine 或接收逻辑被条件跳过。

go并发编程为什么会阻塞_go阻塞原因与解决思路

channel 操作未配对导致死锁

Go 中最典型的阻塞是向无缓冲 channel 发送数据时,没有协程在另一端接收,send 会永久阻塞当前 goroutine。运行时检测到所有 goroutine 都在等待(包括 main),就会 panic fatal error: all goroutines are asleep - deadlock

常见于忘记启动接收协程,或接收逻辑被条件跳过:

ch := make(chan int)
ch <- 42 // 这里立刻死锁:没人收
  • 无缓冲 channel 必须「发送」和「接收」严格配对,且至少一个在运行中
  • make(chan int, 1) 创建带缓冲 channel 可缓解,但缓冲区满后仍会阻塞
  • 调试时加 go func() { fmt.Println(receiving...); 快速验证是否漏了 receiver

select 默认分支缺失引发无限等待

select 中所有 channel 操作都不可达(如全满/全空),又没写 default,goroutine 就会挂起——这不是死锁,但行为上就是卡住不动。

例如从多个 channel 读取,但其中某个始终没数据、也没设超时:

知了追踪
知了追踪

AI智能信息助手,智能追踪你的兴趣资讯

下载
select {
case v := <-ch1:
    fmt.Println(v)
case v := <-ch2:
    fmt.Println(v)
// 缺少 default 或 timeout,ch1 和 ch2 都没数据时就永远等
  • 想非阻塞尝试读写,必须加 default: 分支(哪怕只写 default: continue
  • 想限时等待,用 time.Aftertime.NewTimer 接入 select
  • select {} 是经典空阻塞写法,常用于让 goroutine 永久休眠,但要确认这是有意为之

sync.WaitGroup 使用不当造成 main 提前退出或 hang 住

WaitGroup 本身不阻塞,但误用会导致预期外的阻塞或 panic。最常见的是:Add() 调用晚于 Go 启动,或 Done() 被漏调、多调。

  • 必须在 go 语句前调用 wg.Add(1),否则新 goroutine 可能已执行完 Done(),而 main 已调用 wg.Wait() 返回
  • Done() 被漏调 → Wait() 永远不返回;被多调 → panic panic: sync: negative WaitGroup counter
  • 不要在循环里反复 var wg sync.WaitGroup:每次重声明会丢掉之前的计数,应定义一次、复用

net/http 服务未设超时引发连接级阻塞

HTTP server 默认不设读写超时,客户端异常断连、慢请求、大文件上传未完成等情况,都会让 goroutine 卡在 conn.Read()conn.Write() 上,堆积大量 idle goroutine。

  • http.ServerReadTimeoutWriteTimeoutIdleTimeout 显式控制
  • 不要依赖 context.WithTimeout 在 handler 内部做超时——它只能中断业务逻辑,无法终止底层 TCP 连接读写
  • 长连接场景(如 WebSocket)需额外处理 Ping/Pong 心跳,避免因网络闪断导致连接滞留

实际并发阻塞往往不是单点问题,而是 channel 设计、超时策略、资源释放三者耦合的结果。尤其要注意:Go 不会自动回收“卡住”的 goroutine,只要它还在等,就会一直占内存和栈空间。

相关文章

编程速学教程(入门课程)
编程速学教程(入门课程)

编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

187

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

279

2023.10.25

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

315

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

537

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

Golang channel原理
Golang channel原理

本专题整合了Golang channel通信相关介绍,阅读专题下面的文章了解更多详细内容。

245

2025.11.14

golang channel相关教程
golang channel相关教程

本专题整合了golang处理channel相关教程,阅读专题下面的文章了解更多详细内容。

342

2025.11.17

C++ 单元测试与代码质量保障
C++ 单元测试与代码质量保障

本专题系统讲解 C++ 在单元测试与代码质量保障方面的实战方法,包括测试驱动开发理念、Google Test/Google Mock 的使用、测试用例设计、边界条件验证、持续集成中的自动化测试流程,以及常见代码质量问题的发现与修复。通过工程化示例,帮助开发者建立 可测试、可维护、高质量的 C++ 项目体系。

3

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.8万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号