首頁 >後端開發 >Golang >如何解決 Go 並發死鎖:「所有 goroutine 都在睡覺」?

如何解決 Go 並發死鎖:「所有 goroutine 都在睡覺」?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-12-28 13:31:13861瀏覽

How to Resolve Go Concurrency Deadlocks:

並發中的死鎖錯誤:「拋出:所有Goroutine 都處於睡眠狀態」

在Go 中處理並發時,如果所有Goroutines 都處於休眠狀態,則可能會發生死鎖goroutine 正在等待彼此執行操作。與此問題相關的一個常見錯誤是「拋出:所有goroutine 都在睡眠- 死鎖!」

理解問題

考慮以下Go 程序:

package main

import (
    "fmt"
)

func total(ch chan int) {
    res := 0
    for iter := range ch {
        res += iter
    }
    ch <- res
}

func main() {
    ch := make(chan int)
    go total(ch)
    ch <- 1
    ch <- 2
    ch <- 3
    fmt.Println("Total is ", <-ch)
}

執行這個程式時,我們遇到錯誤「throw: all goroutine are sleep - deadlock!」原因是total函數中的範圍循環永遠不會退出,因為我們永遠不會關閉ch通道。結果,在 main 函數中等待接收結果的 goroutine 永遠不會收到它。

解決死鎖

要解決這個死鎖,我們需要關閉ch 通道指示不再發送任何值。此外,我們可以使用單獨的通道傳回結果,從而防止在同一通道上直接發送和接收。

下面修改後的程式解決了這些問題:

package main

import (
    "fmt"
)

func total(in chan int, out chan int) {
    res := 0
    for iter := range in {
        res += iter
    }
    out <- res // sends back the result
}

func main() {
    ch := make(chan int)
    rch := make(chan int)
    go total(ch, rch)
    ch <- 1
    ch <- 2
    ch <- 3
    close(ch) // this will end the loop in the total function
    result := <-rch // waits for total to give the result
    fmt.Println("Total is ", result)
}

透過關閉ch 通道並使用單獨的 rch 通道來獲取結果,我們消除了死鎖並允許程式正確執行。

以上是如何解決 Go 並發死鎖:「所有 goroutine 都在睡覺」?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn