WaitGroup死锁(没有错误消息)

时间:2016-09-20 21:10:20

标签: go deadlock

我在创建几个goroutine时遇到了一个问题,使用sync.WaitGroup在适当的时候将所有内容组合在一起。

基本上,我尝试过写这样的东西:

//global var
var wg sync.WaitGroup

//say inside main:
ch1 := make(chan *MyStruct) // data we're after
ch2 := make(chan string) // only used for warnings
result := []*MyStruct{}
for p := range data {
    wg.Add(1)
    go processData(p, ch1, ch2)
}
wg.Wait()
close(ch1)
close(ch2)
for elem := range(ch1) {
    result = append(result, elem)
}
for warn := range(ch2) {
    log.Printf("%s" warn)
}

goroutine函数看起来像这样:

//processData
func processData(p interface{}, ch1 chan *MyStruct, ch2 chan string) {
    defer wg.Done()
    data := &MyStruct{}
    data.raw = p
    //based on certain conditions, this can happen:
    if data.NeedsMoreProcessing() {
        wg.Add(1)
        go additionalProcessing(data, ch2)
    }
    ch1 <- data
}

func additionalProcessing(data *MyStruct, ch chan<- string) {
    defer wg.Done()
    if err := data.ExtraStuff(); err != nil {
        ch <- fmt.Sprintf(
            "Additional processing on element %d failed: %s",
            data.Id,
            err.Error(),
        )
        return
    }
    data.SetAdditionalInfo()
}

AFAIK,我正确地调用wg.Add(在goroutine开始之前),我知道例程需要一段时间(他们使用http.get调用等...)。我没有得到常见的&#34;致命错误:所有goroutines都睡着了 - 死锁!&#34; 错误消息。

相反,Wait来电似乎永远不会回来。当我将该调用包装在它自己的例程中时,问题得到了解决:

go func() {
    wg.Wait()
    close(ch1)
    close(ch2)
}()

但除此之外,一切都保持原样。为什么这样,似乎我们需要在goroutine中调用Wait?在这种情况下,我真的没有看到太大的区别。在我的特定情况下,例程需要几秒钟才能完成,在Wait调用之前确定没有完成例程的风险吗?

0 个答案:

没有答案