有个疑惑,在goroutine中执行ticker,使用context终止退出,关于执行结果的疑惑

发布于 2022-09-12 23:19:37 字数 1201 浏览 29 评论 0

代码如下:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

救赎№ 2022-09-19 23:19:37

defer执行是要时间的,你cancel后直接就退出了。此时ctx.Done()刚收到信号,可能来不及执行defer。你试一下cancel后再休息一秒,结果应该就一致了

↙厌世 2022-09-19 23:19:37

main里面的cancel()执行后,main就退出了,此时整个程序也就退出,所以其他协程可能还没来得及执行相关程序也随着main的退出而退出了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文