有个疑惑,在goroutine中执行ticker,使用context终止退出,关于执行结果的疑惑
代码如下:
package main
import (
"context"
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(time.Second)
ctx, cancel := context.WithCancel(context.Background())
TickerHandle(ticker, ctx)
time.Sleep(3 * time.Second)
cancel()
}
func TickerHandle(ticker *time.Ticker, ctx context.Context) {
go func() {
defer func() {
ticker.Stop()
fmt.Println("Defer Ticker Stop!")
}()
for {
select {
case <-ctx.Done():
fmt.Println("Ticker Stop1")
return
case <-ticker.C:
fmt.Println("Ticker...")
}
}
fmt.Println("Ticker Stop2")
}()
}
执行结果1:
Ticker...
Ticker...
执行结果2:
Ticker...
Ticker...
Ticker...
Ticker Stop1
Defer Ticker Stop!
执行结果3:
Ticker....
Ticker....
Ticker....
Ticker Stop1
执行结果4:
Ticker...
Ticker...
Ticker...
尝试在go1.12~1.16中执行,每次执行结果是不确定的,所以使用context.WithCancel()这种方式是没有办法真正使执行ticker的goroutine停止退出,需要使用channel。
主要是这里有个疑惑,为什么多次执行每次执行结果都不是确定的?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
defer执行是要时间的,你cancel后直接就退出了。此时ctx.Done()刚收到信号,可能来不及执行defer。你试一下cancel后再休息一秒,结果应该就一致了
main里面的cancel()执行后,main就退出了,此时整个程序也就退出,所以其他协程可能还没来得及执行相关程序也随着main的退出而退出了