go的timer.stop()在關(guān)閉時(shí)不會(huì)關(guān)閉它自己的channel
下圖是timer.Stop()函數(shù)的注釋
我們之前用到了很多的timer,每個(gè)協(xié)程一個(gè)timer齐苛,但這個(gè)協(xié)程是在等timer的channel,而協(xié)程里在等待timer的channel,這樣在timer.stop()的時(shí)候timer的channel并不會(huì)收到數(shù)據(jù),導(dǎo)致大量的協(xié)程hung在那里了酌媒。協(xié)程的大概代碼如下:
go func(){
? ?<-timer.C //讀取timer的channel,當(dāng)timer到期時(shí)channel會(huì)讀取到數(shù)據(jù)我注,向下執(zhí)行邏輯呀洲,但當(dāng)timer.stop()被調(diào)用時(shí)审胸,這個(gè)channel并不會(huì)讀取到數(shù)據(jù),導(dǎo)致一直hung在這里利凑,goroutine不會(huì)退出
? ? do something....
}
后來(lái)解決方案修改如下:
go func(){
? ?select{
? ? ? ? ? ? case <-timer.C: //如果是timer到期浆劲,則執(zhí)行相應(yīng)邏輯
? ? ? ? ? ? ? ? ? do something....
? ? ? ? ? ? ?case <-stopChannel: //新增加一個(gè)關(guān)閉標(biāo)志嫌术,如果是這個(gè)關(guān)閉,則直接return
? ? ? ? ? ? ? ? ? ?return
? ? ? }
}
相應(yīng)的之前只是簡(jiǎn)單調(diào)用timer.stop()應(yīng)該被修改成下面的樣子了:
func stop(){
? ? ?close(stopChannel)//這里先關(guān)閉這個(gè)標(biāo)志channel梳侨,保證相應(yīng)的goroutine正常退出
? ? ? timer.stop()//這里調(diào)用正常的timer關(guān)閉
}
這樣就可以保證timer關(guān)閉時(shí)相應(yīng)的調(diào)用協(xié)程也退出了
另外就是要提及下pprof這個(gè)工具蛉威,通過(guò)這個(gè)工具定位到了很多協(xié)程都是在timer處hung住了