我是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 写入通道,因此在读取两个通道后,无需等待。
ABOUTYOU
TA贡献1812条经验 获得超5个赞
事实上,这里并不是真的需要等待小组。但是,如果您想继续试验戈鲁丁和通道,那么您也可以尝试使通道缓冲,例如:
c1 := make(chan string, 1) c2 := make(chan string, 1)
然后发生的事情是,您可以为每个通道写入单个条目而不会阻塞。
慕工程0101907
TA贡献1887条经验 获得超5个赞
读取/写入无缓冲通道是阻塞调用,这意味着这些行:
c <- "foo" c <- "bar"
将挂起,直到您到达从通道中提取值的调用,即这些行:
foo := <-c1 bar := <-c2
死锁的原因是在这两行之前调用。为了移动过去,所有等待组必须完成,但您的等待组不能完成,因为被推迟到/取消阻止。如前所述,在到达 / 之前,无法取消阻止这些内容,并且由于 .你可以看到怎么可能没有进展,因此僵局。wg.Wait()
wg.Wait()
wg.Done()
c <- "foo"
c <- "bar"
foo := <-c1
bar := <-c2
wg.Wait()
最佳做法是避免使用等待组和互斥锁,直到绝对必要。通常,(就像在这种情况下)解决方案在纯Go中是可能的,这些包只会使代码复杂化。
- 3 回答
- 0 关注
- 66 浏览
添加回答
举报
0/150
提交
取消