GO语言:致命错误:所有goroutine都处于休眠状态-死锁
下面的代码可以很好地处理硬编码的JSON数据,但是当我从文件中读取JSON数据时,它就不起作用了。我收到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
致命错误:所有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)你好,欢迎访问堆栈溢出。请考虑在您的答案中添加更多上下文,而不是简单地发布可能或可能无法解决问题的代码片段。