在 Golang 程式中,Channel 促進了 goroutine 之間的通訊。然而,誤用通道可能會導致死鎖,如下面的程式碼所示:
<br>package main<p>import (</p><pre class="brush:php;toolbar:false">"fmt" "sync"
)
func push(c chan int, wgsync.WaitGroup) {
for i := 0; i < 5; i++ { c <- i } wg.Done()
}
func pull(c chan 是🎜>
}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() // Block the main thread until goroutines complete
執行此程式時,您可能會遇到出現以下錯誤:
fatal error: all goroutines are asleep - deadlock!
因此,當每個 goroutine 呼叫 wg.Done() 時,它會修改其本地的 WaitGroup 副本。由於主執行緒會一直等待,直到 wg 指示所有 Goroutine 都已完成,因此它會無限期地等待,因為兩個 Goroutine 都不會更新原始的 WaitGroup。這會導致死鎖。
要解決此問題,我們需要透過引用傳遞 WaitGroup。這可以確保兩個 goroutine 修改 WaitGroup 的相同實例,並向主執行緒正確發出完成訊號。
這是經過更正的程式碼修訂版:
package main<p><br>import (</p><p></p>)<pre class="brush:php;toolbar:false">"fmt" "sync"
)
import (for i := 0; i < 5; i++ { c <- i } wg.Done()
import (
for i := 0; i < 5; i++ { result, ok := <-c fmt.Println(result, ok) } wg.Done()
)
func push(c chan int, wg *sync.WaitGroup) {
var wg sync.WaitGroup wg.Add(2) c := make(chan int) go push(c, &wg) // Pass the WaitGroup by reference using the ampersand go pull(c, &wg) // Pass the WaitGroup by reference using the ampersand wg.Wait()
}
}func main() {}透過引用傳遞WaitGroup,我們確保主執行緒能夠正確判斷兩個goroutines何時完成任務,以避免死鎖。
以上是為什麼在 Go 中按值傳遞 WaitGroup 會導致死鎖,如何解決?的詳細內容。更多資訊請關注PHP中文網其他相關文章!