go的goroutine泄漏

goroutine 泄漏(goroutine leak)是指创建的 goroutine 无法被正常结束和回收,一直处于阻塞状态,占用系统资源。这就像内存泄漏一样,会逐渐消耗系统资源。

让我用几个典型的例子来说明 goroutine 泄漏的情况:

1. channel 发送阻塞导致泄漏:
```go
func leak() {
ch := make(chan string) // 无缓冲channel
go func() {
val := "hello"
ch <- val // 这里会永远阻塞,因为没有接收者
}()
// 函数结束,但goroutine还在运行且阻塞
}
```

2. channel 接收阻塞导致泄漏:
```go
func leak() {
ch := make(chan string)
go func() {
val := <-ch // 这里会永远阻塞,因为没有发送者
fmt.Println(val)
}()
// 函数结束,但goroutine还在运行且阻塞
}
```

3. 无限循环导致泄漏:
```go
func leak() {
go func() {
for { // 无限循环
// 做一些工作
time.Sleep(time.Second)
}
}()
// 没有提供退出机制
}
```

防止 goroutine 泄漏的主要方法:

1. 使用 context 进行控制:
```go
func noLeak(ctx context.Context) {
go func() {
select {
case <-ctx.Done():
return // 可以正常退出
default:
// 做一些工作
}
}()
}
```

2. 使用 done channel 作为退出信号:
```go
func noLeak() {
done := make(chan bool)
go func() {
select {
case <-done:
return
default:
// 做一些工作
}
}()
// 使用完后关闭
close(done)
}
```

3. 确保 channel 操作有超时机制:
```go
func noLeak() {
ch := make(chan string)
go func() {
select {
case ch <- "data":
// 成功发送
case <-time.After(time.Second):
// 超时退出
return
}
}()
}
```

4. 在程序结束前等待所有 goroutine 完成:
```go
func noLeak() {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
// 做一些工作
}()
wg.Wait() // 等待goroutine完成
}
```

识别 goroutine 泄漏的方法:
1. 使用 runtime.NumGoroutine() 监控 goroutine 数量
2. 使用 pprof 工具分析 goroutine 状态
3. 定期检查系统资源使用情况

goroutine 泄漏会导致:
1. 内存使用增加
2. CPU 资源浪费
3. 程序性能下降
4. 可能导致程序崩溃

所以在编写并发程序时,需要特别注意 goroutine 的生命周期管理,确保它们能够正常退出。

 

内存泄漏就是系统分配给程序内存,但是因为程序的异常或错误,导致这部分内存一直被占用或未释放,系统无法回收,造成内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

posted @   仁义礼智信的  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
历史上的今天:
2021-02-05 git 配置不同ssh
2018-02-05 sublime text3 代码速写
2018-02-05 meta name="viewport" content="width=device-width,initial-scale=1.0" 解释
点击右上角即可分享
微信分享提示