解決Goroutine 死鎖
使用並發Golang 程式時,可能會遇到死鎖錯誤:「fatal error: all goroutine are sleep -僵局!當多個 goroutine 互相等待執行任務時會出現此錯誤,從而造成死鎖情況。
考慮以下程式碼:
<code class="go">func producer(ch chan int, d time.Duration, num int) { for i := 0; i < num; i++ { ch <- i time.Sleep(d) } } func main() { ch := make(chan int) go producer(ch, 100*time.Millisecond, 2) go producer(ch, 200*time.Millisecond, 5) for { fmt.Println(<-ch) } close(ch) }</code>
此程式碼建立兩個傳送值的生產者 goroutine到同一個頻道。主協程無限循環地不斷從通道接收值。
問題的出現是因為生產者是“短暫的”,在有限的時間後停止發送值,但主協程繼續接收值不休。這會造成死鎖,因為通道永遠不會關閉以發出不再發送任何值的信號。
為了解決此死鎖,我們必須確保當所有生產者完成其任務時關閉通道。實現此目的的有效方法是使用同步原語,例如sync.WaitGroup。
這是程式碼的修改版本:
<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) { defer wg.Done() for i := 0; i < num; i++ { ch <- i time.Sleep(d) } } func main() { wg := &sync.WaitGroup{} ch := make(chan int) wg.Add(1) go producer(ch, 100*time.Millisecond, 2, wg) wg.Add(1) go producer(ch, 200*time.Millisecond, 5, wg) go func() { wg.Wait() close(ch) }() for v := range ch { fmt.Println(v) } }</code>
在此程式碼中,我們傳遞了一個sync.WaitGroup。 WaitGroup 到每個生產者 goroutine。每個生產者在開始之前遞增等待組,並在完成時遞減。主協程使用 wg.Wait() 等待所有生產者完成。一旦所有生產者完成工作,主協程就會關閉通道。
此解決方案確保只有在所有生產者完成工作後才關閉通道,從而防止死鎖情況。
以上是Golang中使用Goroutines和Channel時如何防止死鎖?的詳細內容。更多資訊請關注PHP中文網其他相關文章!