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 而无法启动它。
我想了解 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 而无法启动它。