我是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 關注
- 78 瀏覽
添加回答
舉報
0/150
提交
取消