goroutines 死锁,需要一些解释

goroutines deadlock, need some explanation

我想了解 Go 例程在这里是如何工作的。

问题一: go-routine 是否从主 GO routine/func 继承了任何东西??

问题二: 还想知道如果我将 "hi whats up" 发送到 msg 通道为什么它没有被 LINE:13 的 go-routine 接收到????

  1 package main
  2 
  3 import "fmt"
  4 
  5 func main() {
  6     msg := make(chan string, 2) //channel (bidirectional channel) of type string
  7 
  8     msg <- "hi whats up"
  9     fmt.Println("*****I am main go routine*****")
 10 
 11     go func() {
 12         fmt.Println("*****HI ABHI *****\n")
 13         temp := <-msg
 14         fmt.Println(temp)
 15         msg <- "Hello from a goroutine!" //send a string through the channel
 16     }()
 17 
 18     fmt.Println("Main routine waiting for message")
 19 
 20     fmt.Println(<-msg) //receive the string from the channel
 21     fmt.Println(<-msg)
 22 }  

出现以下错误:

*****I am main go routine*****

Main routine waiting for message

hi whats up

*****HI ABHI *****

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:

main.main()

/Users//work/go/src/github.com/Golang_play/goroutine/goroutine.go:21 +0x1e6

goroutine 5 [chan receive]:

main.main.func1(0xc420054060)

/Users/work/go/src/github.com/Golang_play/goroutine/goroutine.go:13 +0x98 created by main.main /Users/work/go/src/github.com/Golang_play/goroutine/goroutine.go:11 +0xe2 exit status 2

同样在下面的程序中,第 14 行从不打印。

 5 func main() {
  6     msg := make(chan string, 2) //channel (bidirectional channel) of type string
  7 
  8     msg <- "hi whats up"
  9     fmt.Println("*****I am main go routine*****")
 10 
 11     go func() {
 12         fmt.Println("*****HI ABHI *****\n")
 13         temp := <-msg
 14         fmt.Println(temp)
 15         //msg <- "Hello from a goroutine!" //send a string through the channel
 16     }()

您正在尝试在同一频道上以两种方式发送消息,但您没有做任何事情来保证谁阅读了哪些消息。主 goroutine 完全有可能在 func goroutine 尝试从通道读取之前收到 它发送的消息 。如果发生这种情况,两个 goroutine 都会卡住等待永远不会到达的消息。

使用两个频道。

新启动的goroutine可以通过闭包从外部代码捕获变量,除此之外不继承任何东西。

第 13 行和第 20 行的通道接收之间存在竞争。如果第 20 行的读取首先执行,它将消耗通道上的唯一值,最终,两个 goroutine 都被阻塞从通道读取,因此出现死锁错误。如果你想从 goroutine 中获取一个值,最好有另一个通道而不是试图在一个通道上对它进行排序。

这是一个工作示例:

package main

import "fmt"

func main() {
    msg := make(chan string)
    go func() {
        temp := <-msg
        fmt.Println(temp)
        msg <- "Hello from a goroutine!"
    }()

    msg <- "hi whats up"
    fmt.Println(<-msg)
}

对于无缓冲通道,消息传递是同步的,因此 goroutine 永远不会接收来自它们自己的消息(因为同一个 goroutine 必须同时发送和接收才能发生这种情况)。请注意,此设计要求您在向 msg 通道写入任何内容之前启动 goroutine 读取,否则您将等待 reader 而无法启动它。