go语言基础学习七
GMP能不能去掉P层?会怎么样#
每个 P 有自己的本地队列,大幅度的减轻了对全局队列的直接依赖,所带来的效果就是锁竞争的减少。而 GM 模型的性能开销大头就是锁竞争。
每个 P 相对的平衡上,在 GMP 模型中也实现了 Work Stealing 算法,如果 P 的本地队列为空,则会从全局队列或其他 P 的本地队列中窃取可运行的 G 来运行,减少空转,提高了资源利用率。
goroutine什么情况会发生内存泄漏?如何避免#
goroutine 泄漏 4 种场景#
chan 阻塞永久等待#
G 阻塞读 / 写无配套另一端收发,goroutine 永久挂起不退出
ch := make(chan int)
<-ch // 没人写,G卡死
无限 for 死循环无退出条件#
for{}里面无 break、无退出信号,持续常驻
全局变量持有 goroutine 引用#
全局切片 /map 存 G 内大对象,GC 无法回收 G。 全局slice/map是常驻内存,保存了 G 里创建的大结构体 / 变量: G 执行完本该消亡,但全局变量还握着它的引用 → GC 不能回收这块内存,G 资源常驻 = 内存泄漏。
var global []*BigData // 全局
func test(){
go func(){
big:=BigData{}
global=append(global,&big) // 全局持有引用
}()
}
sync.WaitGroup 使用错误#
Add 在 G 内部调用、Done 漏写,Wait 永久阻塞 Add 写到 goroutine 内部:
// 错
var wg sync.WaitGroup
go func(){
wg.Add(1) // goroutine启动后才+1
defer wg.Done()
}()
wg.Wait()
漏写 Done: 协程提前 return 没执行Done,计数器永远不归零,Wait 永久阻塞,goroutine 常驻泄漏。
规避方案#
chan:加超时 / 关闭通道#
循环:设置退出标识、上下文 ctx.Done ()#
不用全局常驻容器存临时任务#
wg.Add 放到 goroutine 启动前,成对 Done#
原创
go-7
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法