了解golang频道:死锁

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了了解golang频道:死锁相关的知识,希望对你有一定的参考价值。

以下代码:

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”命令)。我也尝试过缓冲通道 - 类似的故障。我有问题要明白为什么这不起作用。理解的任何提示? 谢谢。

答案

正如对问题的评论中所述,延迟在主要回归之前不会执行。结果,words的范围永远阻止。

要解决此问题,应用程序必须在所有goroutine完成发送后关闭words。一种方法是使用wait group。等待组针对每个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。常见问题解答explains why this is a problem

以上是关于了解golang频道:死锁的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Golang 频道写入永远阻塞?

golang goroutine例子[golang并发代码片段]

Golang Functional Options 来了解一下?

golang代码片段(摘抄)

golang-锁-死锁,互斥锁,读写锁

代码片段 - Golang 实现简单的 Web 服务器