第一份代码如下
package main
import (
"fmt"
"time"
)
func main() {
var ball = make(chan string)
kickBall := func(playerName string) {
for {
fmt.Print(<-ball, "传球", "\n")
time.Sleep(1 * time.Second)
ball <- playerName
}
}
go kickBall("张三")
go kickBall("李四")
go kickBall("王五")
go kickBall("赵六")
ball <- "裁判"
var c chan bool
<-c
}
分界线
第二份代码如下
package main
func main() {
var c chan bool
<-c
}
1
0o0O0o0O0o 2023-07-06 08:44:51 +08:00 via iPhone
第一份代码也是有 panic 的潜力的,建议读 https://tour.go-zh.org/concurrency/2
|
2
aarontian 2023-07-06 08:45:29 +08:00 via Android
所有线程都阻塞就 panic 了
|
3
rekulas 2023-07-06 08:48:14 +08:00
第二个没有运行中的协程,编译器直接判断死锁了,随便加一个就可以了
|
4
rekulas 2023-07-06 08:49:45 +08:00
说错 不是编译器判断 是运行中判断的
|
5
Rooger 2023-07-06 09:01:27 +08:00
能写出第二个代码,有一个基本的原则你没有弄明白。即 channel 的用途:在不同的协程之间进行消耗的传递,而第二份代码,即对 channel 没有初始化,也没有额外的协程存在。
|
6
0o0O0o0O0o 2023-07-06 09:17:17 +08:00
@0o0O0o0O0o #1 emmm 抱歉看错了
|
7
Seanfuck 2023-07-06 09:24:10 +08:00
chan 不是要 make 来创建吗,var **也行?
|
8
8355 2023-07-06 09:29:40 +08:00
第二个没懂先看基础文档吧。。。。。
|
9
paceewang1 2023-07-06 09:48:52 +08:00
@Seanfuck var 是声明
|
10
hsfzxjy 2023-07-06 09:59:00 +08:00 via Android
所有 goroutine 都睡了就会 panic
|
11
CarrieBauch OP @aarontian
明白了,panic 会发生在所有的协程都被阻塞的情况下。把第一个程序简化为这样之后,也不会 panic 。因为 go 启动的一个协程在不断的运行,所以不会 panic package main func main() { go func() { for { } }() var c chan bool <-c } |
12
CarrieBauch OP @rekulas
明白了,多谢多谢 |
13
CarrieBauch OP @hsfzxjy 感谢感谢
|
14
Richard14 2023-07-06 10:15:56 +08:00
我看 op 的贴,把第二段代码加了个放东西的协程,感觉就不会出错了,然而还是报错,OP 知道啥原因吗?
package main import ( "fmt" ) func main() { var c chan bool go func() { c <- true }() fmt.Println(<-c) } |
16
CarrieBauch OP @Richard14
你把代码改成这样,就不会 panic 了 原因就是 channel 没有初始化,只是做了 var 的声明 package main import ( "fmt" ) func main() { //var c chan bool c := make(chan bool) go func() { c <- true }() fmt.Println(<-c) } |
17
lasuar 2023-07-06 10:45:20 +08:00
go 允许对一个 nil chan 进行读操作,这会导致阻塞。第二个例子会监测到死锁 panic 的原因是程序中没有其他 goroutine 正在运行。值得说明的是,这里不仅仅是要求有其他 goroutine 在运行,而且也不能全部同时阻塞,此时 go 运行时会监测到程序无法解除阻塞状态,从而再次导致死锁 panic 。
下面的代码说明了 [其他 goroutine 不能全部同时阻塞的情况] : ``` go func() { var cc = make(chan bool) <-cc }() var c = make(chan bool) <-c ``` 最后:通过第二段代码(无论 chan 是否通过 make 创建)来阻塞主程序不是合理的实践,原因上面说了,当程序中只剩下一个 goroutine (主)在运行时,这种代码会死锁 panic 并退出。 |
18
crescentBLADE 2023-07-06 10:48:30 +08:00
@Richard14 把 “var c chan bool” 改成 “var c = make(chan bool)”就可以了,未初始化的 chan 变量并没有分配任何内存空间,因此无法进行读写操作
|
19
codehz 2023-07-06 13:40:50 +08:00
import 一个"net"也不会 panic🤣🤣🤣
|
20
BinaryDH 2023-07-06 17:47:57 +08:00
唉,问了一个问题,还得到了一份错误的答案!好好看看 channel 和 groutine 的文档吧,每一次阅读和编写 demo ,相信你都能有不同的提升。
|
21
CarrieBauch OP @BinaryDH 求明说,或者给一个去验证的方向
|