go - 了解 golang channel : deadlock

标签 go deadlock

以下代码:

package main

import (
    "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

我的理解是 channel 词会阻塞作者和读者来达到某种同步。我正在尝试为所有 goroutines(编写器)使用单个 channel ,并在 main 中使用单个读取器(使用“范围”命令)。 我也尝试过缓冲 channel - 类似的失败。 我很难理解为什么这不起作用。有什么有助于理解的技巧吗?
谢谢。

最佳答案

如问题评论中所述,直到 main 返回时才会执行延迟。因此,words 的范围将永远阻塞。

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

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。常见问题explains why this is a problem .

关于go - 了解 golang channel : deadlock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53687392/

相关文章:

go - 如何通过 golang 中的 CGO 将 Go 字符串复制到 C char *?

go - 使用 golang 诊断从 unix 套接字读取非常慢(1 分钟对 netcat 中的 1 秒)

google-app-engine - 拉取任务队列中出现 INVALID_REQUEST 错误

java - RMI死锁怎么会发生呢?

java - 银行转账同步

java - 这种情况下会出现死锁吗?

C 死锁检测线程库

c++ - 为什么如果我注释了 "while" block ,程序就会死锁?其中的 "yield"行有何作用?

go - 如何将值放在golang中的可选字符串参数中?

postgresql - GORM 创建可能已经存在的记录