首页 >后端开发 >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