proper way of waiting for a go routine to finish

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

proper way of waiting for a go routine to finish

问题

我希望知道在退出程序之前等待一个go routine完成的正确方法。阅读其他答案,似乎使用一个bool类型的通道可以解决问题,就像这样Playground链接

func do_stuff(done chan bool) {
    fmt.Println("Doing stuff")
    done <- true
}

func main() {
    fmt.Println("Main")
    done := make(chan bool)
    go do_stuff(done)
    <-done
    // <-done
}

我有两个问题:

  • 为什么<-done能够正常工作?

  • 如果我取消注释最后一行会发生什么?我会得到一个死锁错误。这是因为通道是空的,没有其他函数向其发送值吗?

英文:

I wish to know what is the proper way of waiting for a go routine to finish before exiting the program. Reading some other answers it seems that a bool chan will do the trick, as in Playground link

func do_stuff(done chan bool) {
	fmt.Println(&quot;Doing stuff&quot;)
	done &lt;- true
}

func main() {
	fmt.Println(&quot;Main&quot;)
	done := make(chan bool)
	go do_stuff(done)
	&lt;-done
	//&lt;-done
}

I have two questions here:

  • why the <- done works at all?

  • what happens if I uncomment the last line? I have a deadlock error. Is this because the channel is empty and there is no other function sending values to it?

答案1

得分: 11

为什么<- done会起作用?

  • 这是因为运行时检测到你在其他地方向通道写入了数据。

如果我取消注释最后一行会发生什么?

  • 运行时会聪明地知道没有其他数据被写入,从而导致死锁。

额外奖励,如果你的内存非常有限,你可以使用done := make(chan struct{})done <- struct{}{}struct{}保证使用0内存。

英文:

Why the &lt;- done works at all?

  • It works because the runtime detects that you're writing something to the channel somewhere else.

what happens if I uncomment the last line?

  • The runtime is smart enough to know that there's nothing else being written and it deadlocks.

Bonus, if you're extremely limited on memory, you can use done := make(chan struct{}) and done &lt;- struct{}{}, struct{} is guaranteed to use 0 memory.

答案2

得分: 11

监听通道<- done是一个阻塞操作,所以你的程序在发送true或false之前不会继续执行,即done <- true

根据情况,你的问题可能有几个不同的答案。

例如,假设你想并行执行一系列耗时的函数调用。

我会使用sync包来实现。

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func() {
            longOp()
            wg.Done()
        }()
    }
    // 等待直到wg.Done被调用10次
    // 因为我们调用了wg.Add(1) 10次
    wg.Wait()
}

func longOp() {
    time.Sleep(time.Second * 2)
    fmt.Println("long op done")
}

以上是一个使用sync.WaitGroup实现并行函数调用的示例代码。

英文:

Listening to channel &lt;- done, is a blocking operation, so your program won't continue until true or false is sent i.e. done &lt;- true.

Your question can have a few different answers depending on the circumstance.

For instance, suppose you wanted to parallelize a series of function calls that take a long time.

I would use the sync package for this

package main

import (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;time&quot;
)

func main() {
    var wg sync.WaitGroup
    for i := 0; i &lt; 10; i++ {
        wg.Add(1)
        go func() {
            longOp()
            wg.Done()
        }()
    }
    // will wait until wg.Done is called 10 times
    // since we made wg.Add(1) call 10 times
    wg.Wait()
}

func longOp() {
    time.Sleep(time.Second * 2)
    fmt.Println(&quot;long op done&quot;)
}

huangapple
  • 本文由 发表于 2014年9月21日 08:08:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/25954481.html
匿名

发表评论

匿名网友

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

确定