使用等待组的并发性

我是Go语言的新手,正在寻找一些关于并发模型的帮助。假设我想同时进行2个http调用,并等待它们都完成,然后处理/合并响应数据。这是我的代码


func main() {

    var wg sync.WaitGroup

    wg.Add(2)

    c1 := make(chan string)

    c2 := make(chan string)

    go foo(c1, &wg)

    go bar(c2, &wg)

    wg.Wait()

    foo := <-c1

    bar := <-c2

    fmt.Println("foo: ", foo)

    fmt.Println("bar: ", bar)

}


func foo(c chan string, wg *sync.WaitGroup) {

    defer wg.Done()

    c <- "foo"

}


func bar(c chan string, wg *sync.WaitGroup) {

    defer wg.Done()

    c <- "bar"

}

但是,当我运行它时,它给出了错误fatal error: all goroutines are asleep - deadlock!


我可以在没有WaitGroup的情况下让它工作,但只是好奇为什么这会陷入僵局,以及最好的方法是什么?


慕村225694
浏览 67回答 3
3回答

富国沪深

大流子流器将阻止等待写入通道,因为通道读取发生在大流子流结束之后(在wg.完成),因此出现死锁。这里的简单解决方案是摆脱等待组。通道读取操作将阻塞,直到 goroutine 写入通道,因此在读取两个通道后,无需等待。

ABOUTYOU

事实上,这里并不是真的需要等待小组。但是,如果您想继续试验戈鲁丁和通道,那么您也可以尝试使通道缓冲,例如:c1&nbsp;:=&nbsp;make(chan&nbsp;string,&nbsp;1) c2&nbsp;:=&nbsp;make(chan&nbsp;string,&nbsp;1)然后发生的事情是,您可以为每个通道写入单个条目而不会阻塞。

慕工程0101907

读取/写入无缓冲通道是阻塞调用,这意味着这些行:c&nbsp;<-&nbsp;"foo" c&nbsp;<-&nbsp;"bar"将挂起,直到您到达从通道中提取值的调用,即这些行:foo&nbsp;:=&nbsp;<-c1 bar&nbsp;:=&nbsp;<-c2死锁的原因是在这两行之前调用。为了移动过去,所有等待组必须完成,但您的等待组不能完成,因为被推迟到/取消阻止。如前所述,在到达 / 之前,无法取消阻止这些内容,并且由于 .你可以看到怎么可能没有进展,因此僵局。wg.Wait()wg.Wait()wg.Done()c <- "foo"c <- "bar"foo := <-c1bar := <-c2wg.Wait()最佳做法是避免使用等待组和互斥锁,直到绝对必要。通常,(就像在这种情况下)解决方案在纯Go中是可能的,这些包只会使代码复杂化。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go