Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
GO语言:致命错误:所有goroutine都处于休眠状态-死锁_Go - Fatal编程技术网

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

GO语言:致命错误:所有goroutine都处于休眠状态-死锁,go,Go,下面的代码可以很好地处理硬编码的JSON数据,但是当我从文件中读取JSON数据时,它就不起作用了。我收到致命错误:所有goroutine都处于休眠状态-使用sync.WaitGroup时出现死锁错误 硬编码JSON数据的工作示例: package main import ( "bytes" "fmt" "os/exec" "time" ) func connect(host string) { cmd := exec.Command("ssh", ho

下面的代码可以很好地处理硬编码的JSON数据,但是当我从文件中读取JSON数据时,它就不起作用了。我收到
致命错误:所有goroutine都处于休眠状态-使用
sync.WaitGroup
时出现死锁
错误

硬编码JSON数据的工作示例:

package main

import (
    "bytes"
    "fmt"
    "os/exec"
    "time"
)

func connect(host string) {
    cmd := exec.Command("ssh", host, "uptime")
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%s: %q\n", host, out.String())
    time.Sleep(time.Second * 2)
    fmt.Printf("%s: DONE\n", host)
}

func listener(c chan string) {
    for {
        host := <-c
        go connect(host)
    }
}

func main() {
    hosts := [2]string{"user1@111.79.154.111", "user2@111.79.190.222"}
    var c chan string = make(chan string)
    go listener(c)

    for i := 0; i < len(hosts); i++ {
        c <- hosts[i]
    }
    var input string
    fmt.Scanln(&input)
}
user@user-VirtualBox:~/go$ go run channel.go
user1@111.79.154.111: " 09:46:40 up 86 days, 18:16,  0 users,  load average: 5"
user2@111.79.190.222: " 09:46:40 up 86 days, 17:27,  1 user,  load average: 9"
user1@111.79.154.111: DONE
user2@111.79.190.222: DONE
package main

import (
    "bytes"
    "fmt"
    "os/exec"
    "time"
    "encoding/json"
    "os"
    "sync"
)

func connect(host string) {
    cmd := exec.Command("ssh", host, "uptime")
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%s: %q\n", host, out.String())
    time.Sleep(time.Second * 2)
    fmt.Printf("%s: DONE\n", host)
}

func listener(c chan string) {
    for {
        host := <-c
        go connect(host)
    }
}

type Content struct {
    Username string `json:"username"`
    Ip       string `json:"ip"`
}

func main() {
    var wg sync.WaitGroup

    var source []Content
    var hosts []string
    data := json.NewDecoder(os.Stdin)
    data.Decode(&source)

    for _, value := range source {
        hosts = append(hosts, value.Username + "@" + value.Ip)
    }

    var c chan string = make(chan string)
    go listener(c)

    for i := 0; i < len(hosts); i++ {
        wg.Add(1)
        c <- hosts[i]
        defer wg.Done()
    }

    var input string
    fmt.Scanln(&input)

    wg.Wait()
}
不工作-读取JSON数据文件的示例:

package main

import (
    "bytes"
    "fmt"
    "os/exec"
    "time"
)

func connect(host string) {
    cmd := exec.Command("ssh", host, "uptime")
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%s: %q\n", host, out.String())
    time.Sleep(time.Second * 2)
    fmt.Printf("%s: DONE\n", host)
}

func listener(c chan string) {
    for {
        host := <-c
        go connect(host)
    }
}

func main() {
    hosts := [2]string{"user1@111.79.154.111", "user2@111.79.190.222"}
    var c chan string = make(chan string)
    go listener(c)

    for i := 0; i < len(hosts); i++ {
        c <- hosts[i]
    }
    var input string
    fmt.Scanln(&input)
}
user@user-VirtualBox:~/go$ go run channel.go
user1@111.79.154.111: " 09:46:40 up 86 days, 18:16,  0 users,  load average: 5"
user2@111.79.190.222: " 09:46:40 up 86 days, 17:27,  1 user,  load average: 9"
user1@111.79.154.111: DONE
user2@111.79.190.222: DONE
package main

import (
    "bytes"
    "fmt"
    "os/exec"
    "time"
    "encoding/json"
    "os"
    "sync"
)

func connect(host string) {
    cmd := exec.Command("ssh", host, "uptime")
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%s: %q\n", host, out.String())
    time.Sleep(time.Second * 2)
    fmt.Printf("%s: DONE\n", host)
}

func listener(c chan string) {
    for {
        host := <-c
        go connect(host)
    }
}

type Content struct {
    Username string `json:"username"`
    Ip       string `json:"ip"`
}

func main() {
    var wg sync.WaitGroup

    var source []Content
    var hosts []string
    data := json.NewDecoder(os.Stdin)
    data.Decode(&source)

    for _, value := range source {
        hosts = append(hosts, value.Username + "@" + value.Ip)
    }

    var c chan string = make(chan string)
    go listener(c)

    for i := 0; i < len(hosts); i++ {
        wg.Add(1)
        c <- hosts[i]
        defer wg.Done()
    }

    var input string
    fmt.Scanln(&input)

    wg.Wait()
}

Go程序在主功能结束时结束。

程序执行首先初始化主包,然后调用main函数。当函数调用返回时,程序退出。它不会等待其他(非主)goroutine完成

因此,您需要等待goroutines完成。常见的解决方案是使用对象

同步goroutine的最简单代码:

package main

import "fmt"
import "sync"

var wg sync.WaitGroup // 1

func routine() {
    defer wg.Done() // 3
    fmt.Println("routine finished")
}

func main() {
    wg.Add(1) // 2
    go routine() // *
    wg.Wait() // 4
    fmt.Println("main finished")
}
用于同步多个goroutine

package main

import "fmt"
import "sync"

var wg sync.WaitGroup // 1

func routine(i int) {
    defer wg.Done() // 3
    fmt.Printf("routine %v finished\n", i)
}

func main() {
    for i := 0; i < 10; i++ {
        wg.Add(1) // 2
        go routine(i) // *
    }
    wg.Wait() // 4
    fmt.Println("main finished")
}
而不是

wg.Add(1)
go g(f(x))

谢谢你对格泽戈尔兹的非常好和详细的解释。 我想指出的一点是,通常需要线程化的func不会出现在
main()
中,因此我们会有如下内容:

package main

import (
    "bufio"
    "fmt"
    "io"
    "io/ioutil"
    "math/rand"
    "os"
    "reflect"
    "regexp"
    "strings"
    "sync"
    "time"
)

var wg sync.WaitGroup    // VERY IMP to declare this globally, other wise one   //would hit "fatal error: all goroutines are asleep - deadlock!"

func doSomething(arg1 arg1Type) {
     // cured cancer
}

func main() {
    r := rand.New(rand.NewSource(time.Now().UnixNano()))
    randTime := r.Intn(10)
    wg.Add(1)    
    go doSomething(randTime)
    wg.Wait()
    fmt.Println("Waiting for all threads to finish")
}
我想指出的是,
wg
的全局声明对于所有线程在
main()

之前完成非常重要

package main

import (
    "bytes"
    "fmt"
    "os/exec"
    "time"
    "sync"
)

func connect(host string, wg *sync.WaitGroup) {
    defer wg.Done()
    cmd := exec.Command("ssh", host, "uptime")
    var out bytes.Buffer
    cmd.Stdout = &out
    err := cmd.Run()
    if err != nil {
        fmt.Println(err)
    }
    fmt.Printf("%s: %q\n", host, out.String())
    time.Sleep(time.Second * 2)
    fmt.Printf("%s: DONE\n", host)
}

func listener(c chan string,wg *sync.WaitGroup) {
    for {
        host,ok := <-c
        // check channel is closed or not
        if !ok{
            break
        }
        go connect(host)
    }

}

func main() {
    var wg sync.WaitGroup
    hosts := [2]string{"user1@111.79.154.111", "user2@111.79.190.222"}
    var c chan string = make(chan string)
    go listener(c)

    for i := 0; i < len(hosts); i++ {
        wg.Add(1)
        c <- hosts[i]
    }
    close(c)
    var input string
    fmt.Scanln(&input)
    wg.Wait()
}
主程序包
进口(
“字节”
“fmt”
“os/exec”
“时间”
“同步”
)
func connect(主机字符串,wg*sync.WaitGroup){
推迟工作组完成()
cmd:=exec.Command(“ssh”,主机,“正常运行时间”)
var输出字节。缓冲区
cmd.Stdout=&out
err:=cmd.Run()
如果错误!=零{
fmt.Println(错误)
}
fmt.Printf(“%s:%q\n”,主机,out.String())
时间。睡眠(时间。秒*2)
fmt.Printf(“%s:DONE\n”,主机)
}
func侦听器(c chan字符串,wg*sync.WaitGroup){
为了{

主持人,ok:=我从昨天起就一直在使用GO(甚至不到一天)因此,虽然我一直在阅读文档,但我真的知道的不多。上面的代码是一天学习/实践的结果。我到底应该把睡眠放在哪里?我查看了这个例子。@Innazzz看第一个答案。我想我把事情放错地方了。
致命错误:所有goroutine都睡着了-死锁!
伙计们,我更新了上面的帖子beca使用至少有一个进展,但是这次出现了
死锁
。我移动了
wg
行,但找不到正确的位置。@Innazzz更新帖子不是你能想到的最好的方法。现在答案没有意义,不再可用。是的,wg.Done()调用应该在goroutines内部。不一定。您只需要确保传递的是指针,这样就不会得到副本…
wg:=&sync.WaitGroup{}
函数:
func goDo(…,wg*sync.WaitGroup)你好,欢迎访问堆栈溢出。请考虑在您的答案中添加更多上下文,而不是简单地发布可能或可能无法解决问题的代码片段。