2017-03-13 57 views
1

我正面臨一個煩人的問題。當我嘗試使用wg.Add()來同步我的例程時,會引發死鎖錯誤。嘗試同步goroutines時出現死鎖錯誤

package main 

import (
    "fmt" 
    "sync" 
) 

func hello(ch chan int, num int, wg *sync.WaitGroup) { 
    for { 
     i := <-ch 
     if i == num { 
      fmt.Println("Hello number:", i) 
      ch <- (num - 1) 
      defer wg.Done() // Same happens without defer 
      return 
     } 
     ch <- i 
    } 
} 

func main() { 
    fmt.Println("Start") 

    var wg sync.WaitGroup 
    ch := make(chan int) 

    for i := 0; i < 10; i++ { 
     wg.Add(1) 
     go hello(ch, i, &wg) 
    } 

    ch <- 9 

    wg.Wait() 

    fmt.Println("End") 
} 

輸出:

Start 
Hello number: 9 
Hello number: 8 
Hello number: 7 
Hello number: 6 
Hello number: 5 
Hello number: 4 
Hello number: 3 
Hello number: 2 
Hello number: 1 
Hello number: 0 
fatal error: all goroutines are asleep - deadlock! 

goroutine 1 [semacquire]: 
sync.runtime_Semacquire(0xc04203a20c) 
     C:/Go/src/runtime/sema.go:47 +0x3b 
sync.(*WaitGroup).Wait(0xc04203a200) 
     C:/Go/src/sync/waitgroup.go:131 +0x81 
main.main() 
     C:/Users/Augusto Dias/Documents/GoLang/MT.go:34 +0x1a0 

goroutine 18 [chan send]: 
main.hello(0xc0420380c0, 0x0, 0xc04203a200) 
     C:/Users/Augusto Dias/Documents/GoLang/MT.go:13 +0x197 
created by main.main 
     C:/Users/Augusto Dias/Documents/GoLang/MT.go:29 +0x151 
exit status 2 

當我使用wg.Add(9)外塊,我沒有錯誤。

func main() { 
    fmt.Println("Start") 

    var wg sync.WaitGroup 
    ch := make(chan int) 

    wg.Add(9) // Use wg.Add(10) will raise deadlock too 

    for i := 0; i < 10; i++ { 
     go hello(ch, i, &wg) 
    } 

    ch <- 9 

    wg.Wait() 
    fmt.Println("End") 
} 

輸出:

Start 
Hello number: 9 
Hello number: 8 
Hello number: 7 
Hello number: 6 
Hello number: 5 
Hello number: 4 
Hello number: 3 
Hello number: 2 
Hello number: 1 
End 

這是怎麼回事,我的意思是,爲什麼程序去睡覺時,我等着他們呢?使用相同的通道進行發送和接收可能是此問題的根源?

+0

在您添加10到第一個WaitGroup,在你添加的第二個9.一個goroutine沒有返回。 (你也應該在函數的開始處推遲,而不是在for循環中的條件下)。 – JimB

+0

我在第一個中得到了所有的hellos,什麼例程可以是未返回的? –

+1

你可能會猜到它的編號爲'0',因爲你沒有看到打印的內容,堆棧跟蹤顯示它在第13行的chan發送時被阻塞。 – JimB

回答

2

通道0(呼叫go hello(ch, 0, &wg)),因爲它是最後一個通道活着卡住這條線

ch <- (num - 1) 

它正試圖發送一個通道,但沒有一個人接受它。因此該函數將無限期地等待,永遠不會完成。

如何刪除這個問題

  • 在主迴路
  • 創建一個消費者提出一些建議的渠道ch非阻塞
+0

使ch非阻塞解決了這個問題,謝謝! –

相關問題