GoLang 程序等待,而不是因“所有 goroutine 都在睡觉 - 死锁”而惊慌失措

问题描述 投票:0回答:1

当我使用命令 go run main.go 运行

Program 1
时,它会因错误
all goroutines are asleep - deadlock!
终止,而 Program 2 继续等待并且不会终止。我们没有调用
checkLink
函数,但我们仍然看到不同的行为。你能解释一下吗?

此外,当我运行

go build main.go
程序2的输出的可执行文件时,它被杀死并删除了可执行文件。

节目1

package main

import (
    "fmt"
)

func main() {
    c := make(chan int)
    c <- 4
    x := <-c
    fmt.Println(x)
}

节目2

package main

import (
    "fmt"
    "net/http"
)

func main() {
    c := make(chan int)
    c <- 4
    x := <-c
    fmt.Println(x)
}

func checkLink(link string, c chan string) {
    fmt.Println("checking", link)
    _, err := http.Get(link)
    if err != nil {
        c <- link + " is down"
        return
    }
    c <- link + " is up"
}

注意:我在 MacO 上运行此程序,shell 是 ZSH

go deadlock
1个回答
0
投票

您的 Go 程序似乎由于通道使用不当而遇到了死锁。

在程序 1 和程序 2 中,您都使用 make(chan int) 创建一个无缓冲通道 c。当您尝试发送值时 (c <- 4) on an unbuffered channel without a corresponding receiver, or when there's no receiver ready to receive the value sent on the channel, a deadlock occurs. This is because sending to an unbuffered channel blocks until there's a receiver ready to receive the value.

package main

import (
    "fmt"
)

func main() {
    c := make(chan int) // unbuffered channel
    c <- 4              // attempting to send to an unbuffered channel without a receiver ready
    x := <-c            // this line will never be reached due to the deadlock above
    fmt.Println(x)
}

这是上述代码的更正版本

package main

import (
    "fmt"
)

func main() {
    c := make(chan int)
    go func() {
        c <- 4 // Send value on the channel
    }()
    x := <-c // Receive value from the channel
    fmt.Println(x)
}

在程序 1 中,我们使用 go func() {...}() 将通道操作包装在匿名 goroutine 中。这允许发送操作 c <- 4 to happen concurrently with the receiving operation x := <-c, preventing the deadlock

程序2的更正版本。

package main

import (
    "fmt"
    "net/http"
)

func main() {
    c := make(chan string)
    go checkLink("http://example.com", c)
    result := <-c
    fmt.Println(result)
}

func checkLink(link string, c chan string) {
    fmt.Println("checking", link)
    _, err := http.Get(link)
    if err != nil {
        c <- link + " is down"
        return
    }
    c <- link + " is up"
}
© www.soinside.com 2019 - 2024. All rights reserved.