首页 文章

了解golang Channels :死锁

提问于
浏览
1

以下代码:

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

我的理解是,通道词会阻止作者和读者实现一些同步 . 我正在尝试使用单个通道用于所有goroutine(编写器)和main中的单个读取器(使用"range"命令) . 我也尝试过缓冲通道 - 类似的故障 . 我有问题要明白为什么这不起作用 . 理解的任何提示?
谢谢 .

1 回答

  • 1

    正如对问题的评论所述,延期直到主要回归才会执行 . 结果,超过 words 的范围永远阻挡 .

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

    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 . FAQ explains why this is a problem .

相关问题