【问题标题】:GOLANG: fatal error: all goroutines are asleep - deadlockGOLANG:致命错误:所有 goroutine 都处于休眠状态 - 死锁
【发布时间】:2015-04-02 17:56:11
【问题描述】:
package main
import (
    "fmt"
    "os"
    "os/exec"
    "bufio"
    "reflect"
)

func runTheCommand(ch chan<- string, cmD string)  {
    ouT,_ := exec.Command("sh","-c",cmD).Output()
    ch <- string(ouT)
}
// Readln returns a single line (without the ending \n) from the input buffered reader. An error is returned iff there is an error with the buffered reader.
func Readln(r *bufio.Reader) (string, error) {
    var (isPrefix bool = true
        err error = nil 
        line, ln []byte
    )   
    for isPrefix && err == nil {
        line, isPrefix, err = r.ReadLine()
        ln = append(ln, line...)
    }   
    return string(ln),err
}



func main() {
    var chans = []chan string{}
    f, _ := os.Open("../tmpStatus.config")
    r := bufio.NewReader(f)
    cmD, e := Readln(r)
    for e == nil {
        ch := make(chan string)
        chans = append(chans, ch) 
        go runTheCommand(ch,cmD)
        cmD,e = Readln(r)
    }   

    cases := make([]reflect.SelectCase, len(chans))
    for i, ch := range chans {
        cases[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(ch)}
    }   

    remaining := len(cases)
    for remaining > 0 { 
        chosen, value, ok := reflect.Select(cases)
        if !ok {
            cases[chosen].Chan = reflect.ValueOf(nil)
            remaining -= 1
            continue
        }
        fmt.Printf("%s", value.String())
    }   
}    

此代码正确打印出从通道接收到的所有值。 但最终它退出并出现以下错误:

致命错误:所有 goroutine 都处于休眠状态 - 死锁!

goroutine 1 [select]: reflect.rselect(0xc200283480, 0x22, 0x22, 0xffffffffffffffff, 0x0, ...) /usr/local/go/src/pkg/runtime/chan.c:1212 +0x10d reflect.Select(0xc200066800, 0x22, 0x22, 0x1, 0x0, ...) /usr/local/go/src/pkg/reflect/value.go:1957 +0x1fb

我是 GO 的新手。我参考了谷歌并以某种方式设法编写了一个工作代码。我不完全理解这个脚本是如何工作的,尤其是反射包命令。我的意图是并行执行 ../tmpStatus.config 文件中列出的 unix 命令并打印出结果。我对 GO 提供的并发功能感到兴奋,因此决定尝试一下。现在它打印结果的速度如此之快。直到现在,我都是在 python 中一一做这个。 我在安装到自定义位置的 go 版本 go1.1.2 linux/amd64 中运行了这个脚本。 知道为什么会发生死锁吗?

【问题讨论】:

  • 我们需要查看从您的频道读取的 runTheCommand() 的源代码,但我怀疑您没有使用等待组,或者使用不正确。
  • 嗨 kwolfe,我已经粘贴了我使用的函数。请帮助我。

标签: go deadlock goroutine


【解决方案1】:

您似乎正在尝试从文件中读取数据,然后将工作拆分到多个工作人员(扇出)。我在您的代码中没有看到任何关闭通道。请参阅https://gist.github.com/kylewolfe/7c54018a9ed16517c0dd 了解我所指的模式示例。对于文件的每一行,您将读入一个通道,x 工作人员将从该通道中读取(并反映/执行工作)。

【讨论】:

  • 非常感谢,kwolfe。我在“runTheCommand”函数中添加了 close(ch) 作为最后一个命令,它解决了错误:)
  • 不过,我还是会看看你的设计。我不明白为什么需要一片 chan。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-11
  • 2013-11-22
  • 1970-01-01
  • 2012-09-06
  • 2022-01-21
  • 2021-04-05
相关资源
最近更新 更多