go的timer.stop()在关闭时不会关闭它自己的channel
下图是timer.Stop()函数的注释
我们之前用到了很多的timer,每个协程一个timer,但这个协程是在等timer的channel,而协程里在等待timer的channel,这样在timer.stop()的时候timer的channel并不会收到数据,导致大量的协程hung在那里了。协程的大概代码如下:
go func(){
<-timer.C //读取timer的channel,当timer到期时channel会读取到数据,向下执行逻辑,但当timer.stop()被调用时,这个channel并不会读取到数据,导致一直hung在这里,goroutine不会退出
do something....
}
后来解决方案修改如下:
go func(){
select{
case <-timer.C: //如果是timer到期,则执行相应逻辑
do something....
case <-stopChannel: //新增加一个关闭标志,如果是这个关闭,则直接return
return
}
}
相应的之前只是简单调用timer.stop()应该被修改成下面的样子了:
func stop(){
close(stopChannel)//这里先关闭这个标志channel,保证相应的goroutine正常退出
timer.stop()//这里调用正常的timer关闭
}
这样就可以保证timer关闭时相应的调用协程也退出了
另外就是要提及下pprof这个工具,通过这个工具定位到了很多协程都是在timer处hung住了