为了账号安全,请及时绑定邮箱和手机立即绑定

使用等待组的并发性

使用等待组的并发性

Go
慕村225694 2022-09-19 17:25:56
我是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的情况下让它工作,但只是好奇为什么这会陷入僵局,以及最好的方法是什么?
查看完整描述

3 回答

?
富国沪深

TA贡献1790条经验 获得超9个赞

大流子流器将阻止等待写入通道,因为通道读取发生在大流子流结束之后(在wg.完成),因此出现死锁。

这里的简单解决方案是摆脱等待组。通道读取操作将阻塞,直到 goroutine 写入通道,因此在读取两个通道后,无需等待。


查看完整回答
反对 回复 2022-09-19
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

事实上,这里并不是真的需要等待小组。但是,如果您想继续试验戈鲁丁和通道,那么您也可以尝试使通道缓冲,例如:

c1 := make(chan string, 1)
c2 := make(chan string, 1)

然后发生的事情是,您可以为每个通道写入单个条目而不会阻塞。


查看完整回答
反对 回复 2022-09-19
?
慕工程0101907

TA贡献1887条经验 获得超5个赞

读取/写入无缓冲通道是阻塞调用,这意味着这些行:

c <- "foo"
c <- "bar"

将挂起,直到您到达从通道中提取值的调用,即这些行:

foo := <-c1
bar := <-c2

死锁的原因是在这两行之前调用。为了移动过去,所有等待组必须完成,但您的等待组不能完成,因为被推迟到/取消阻止。如前所述,在到达 / 之前,无法取消阻止这些内容,并且由于 .你可以看到怎么可能没有进展,因此僵局。wg.Wait()wg.Wait()wg.Done()c <- "foo"c <- "bar"foo := <-c1bar := <-c2wg.Wait()

最佳做法是避免使用等待组和互斥锁,直到绝对必要。通常,(就像在这种情况下)解决方案在纯Go中是可能的,这些包只会使代码复杂化。


查看完整回答
反对 回复 2022-09-19
  • 3 回答
  • 0 关注
  • 66 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信