Go Channel 中的死鎖錯誤
在 Go 中,通道提供了 goroutine 之間的一種通訊方式。然而,通道使用不當可能會導致死鎖,導致 goroutine 無限期阻塞。
通道死鎖的一個常見原因是在 goroutine 函數中傳遞值類型而不是指標。這是因為 Go 按值傳遞值類型,這表示建立了值的副本。
考慮這個範例:
<code class="go">import ( "fmt" "sync" ) func push(c chan int, wg sync.WaitGroup) { for i := 0; i < 5; i++ { c <- i } wg.Done() } func pull(c chan int, wg sync.WaitGroup) { for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done() } func main() { var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, wg) go pull(c, wg) wg.Wait() }</code>
運作程式會導致死鎖錯誤:
0 true 1 true 2 true 3 true 4 true throw: all goroutines are asleep - deadlock!
發生死鎖是因為WaitGroup 作為值傳遞給push 和pull 函數。當其中一個 Goroutine 中的 WaitGroup 更新時,更改不會反映在另一個 Goroutine 中,因為它有值的副本。
要解決死鎖,我們需要將 WaitGroup 作為指標傳遞,這確保兩個 goroutine 都在 WaitGroup 的同一個實例上運行。
這是程式碼的正確版本:
<code class="go">import ( "fmt" "sync" ) func push(c chan int, wg *sync.WaitGroup) { for i := 0; i < 5; i++ { c <- i } wg.Done() } func pull(c chan int, wg *sync.WaitGroup) { for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done() } func main() { var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, &wg) go pull(c, &wg) wg.Wait() }</code>
以上是為什麼傳遞值而不是指標會導致 Go Channel 死鎖?的詳細內容。更多資訊請關注PHP中文網其他相關文章!