为了账号安全,请及时绑定邮箱和手机立即绑定

理解 golang 通道:死锁

理解 golang 通道:死锁

Go
jeck猫 2023-05-15 14:52:46
以下代码:package mainimport (    "fmt"    "strings")var data = []string{    "The yellow fish swims slowly in the water",    "The brown dog barks loudly after a drink ...",    "The dark bird bird of prey lands on a small ...",}func main() {    histogram := make(map[string]int)    words := make(chan string)    for _, line := range data {        go func(l string) {            for _, w := range strings.Split(line, " ") {                words <- w            }        }(line)    }    defer close(words)    for w := range words {        histogram[w]++    }    fmt.Println(histogram)}以死锁结束:fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan receive]:main.main()    /tmp/sandbox780076580/main.go:28 +0x1e0我的理解是通道词会阻塞作者和读者来达到某种同步。我正在尝试为所有 goroutines(编写器)使用单个通道,并在 main 中使用单个读取器(使用“范围”命令)。我也尝试过缓冲通道 - 类似的失败。我很难理解为什么这不起作用。有什么有助于理解的技巧吗?
查看完整描述

1 回答

?
绝地无双

TA贡献1946条经验 获得超4个赞

延迟直到 main 返回才执行。结果,范围words永远阻塞。

要解决此问题,应用程序必须words在所有 goroutine 完成发送后关闭。一种方法是使用等待组。等待组为每个 goroutine 递增,当 goroutines 退出时递减。另一个 goroutine 在组上等待并关闭通道。

func main() {

    histogram := make(map[string]int)

    words := make(chan string)


    var wg sync.WaitGroup

    for _, line := range data {

        wg.Add(1)

        go func(l string) {

            for _, w := range strings.Split(l, " ") {

                words <- w

            }

            wg.Done()

        }(line)

    }


    go func() {

        wg.Wait()

        close(words)

    }()


    for w := range words {

        histogram[w]++

    }


    fmt.Println(histogram)

}

奖励修复:问题中的 goroutine 引用了循环变量iine而不是参数l




查看完整回答
反对 回复 2023-05-15
  • 1 回答
  • 0 关注
  • 94 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信