子 goroutine 在其父 goroutine 退出后没有停止。

huangapple go评论81阅读模式
英文:

Child goroutine is not stopped after its parent gorutine exits

问题

我有这段代码:

func sleep(d time.Duration, ch chan<- int) {
	fmt.Println("睡眠中...")
	time.Sleep(d)
	fmt.Println("醒来了...")
	ch <- 0
}

func parent(ctx context.Context) int {
	ch := make(chan int, 1)

	go sleep(3*time.Second, ch)

	select {
	case <-ctx.Done():
		return 1
	case <-ch:
		return 0
	}
}

func app(wg *sync.WaitGroup) {
	defer wg.Done()

	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()

	res := parent(ctx)

	fmt.Println(res)
}

func main() {

	var wg sync.WaitGroup
	wg.Add(1)

	go app(&wg)

	wg.Wait()

	time.Sleep(2 * time.Second)
}

在这个例子中,我有一个带有2秒超时的ctxchildFunc需要3秒才能结束其进程。2秒后,parent函数返回1,因为case <-ctx.Done()。但在主线程中,我再睡眠2秒,我发现childFunc还没有退出,它继续执行其过程,并打印出"醒来了..."。为什么childFunc在其父goroutine结束时没有退出?

以下是输出结果:

睡眠中...
1
醒来了...
英文:

I have this code:

func sleep(d time.Duration, ch chan&lt;- int) {
	fmt.Println(&quot;Sleeping...&quot;)
	time.Sleep(d)
	fmt.Println(&quot;Awake...&quot;)
	ch &lt;- 0
}

func parent(ctx context.Context) int {
	ch := make(chan int, 1)

	go sleep(3*time.Second, ch)

	select {
	case &lt;-ctx.Done():
		return 1
	case &lt;-ch:
		return 0
	}
}

func app(wg *sync.WaitGroup) {
	defer wg.Done()

	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()

	res := parent(ctx)

	fmt.Println(res)
}

func main() {

	var wg sync.WaitGroup
	wg.Add(1)

	go app(&amp;wg)

	wg.Wait()

	time.Sleep(2 * time.Second)
}

In this example, I have a ctx with 2 seconds timeout.
It takes 3 seconds for childFunc to end its process.
After 2 seconds the parent func returns 1 because of case &lt;-ctx.Done().
But in the main thread I sleep for 2 more seconds and I see the childFund hasn't exited and is continuing its process and the Awake... will be printed.
Why childFunc doesn't exit when its parent goroutine finishes?

Here is the output:

Sleeping...
1
Awake...

答案1

得分: 2

我认为你在问为什么一个 goroutine 在创建它的 goroutine 退出时不会退出。除了主 goroutine(当它退出时,包括所有 goroutine 在内的整个程序都会退出),goroutine 在启动时是独立的 - 它们没有“父级”,也没有办法从外部停止它们,包括终止启动它们的 goroutine。如果你想要一个 goroutine 可以被终止,那么你必须自己编写代码,例如在传入的上下文被取消时从 goroutine 中返回。

英文:

I think you're asking why a goroutine doesn't exit when the goroutine that created it exits. Except for the main goroutine (which when it exits, the whole program including all goroutines exit), goroutines are independent when they launch -- they don't have a "parent" and there's no way to stop them from outside, including termination of the goroutine that launched them. If you want a goroutine to be killable then you have to code it yourself, for example by returning from the goroutine when the passed-in context is cancelled.

huangapple
  • 本文由 发表于 2022年11月26日 15:52:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/74580568.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定