一道关于gorotine的死锁问题
一道关于goroutine死锁
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go fmt.Println(<-ch)
ch <- 5
time.Sleep(2 * time.Second)
}
上述结果我选择输出5,分析如下。go关键字启动一个协程A运行,从无缓冲通道ch中读取数据,阻塞等待chan,协程A睡眠,切换到主协程;主协程往通道发送数据,并唤醒协程A,将协程A列入下次可运行队列,协程主动陷入睡眠;golang调度程序调度到协程A,输出5
实际运行上述输出结果为死锁,修改程序
程序B
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go func() {
fmt.Println(<-ch)
}()
ch <- 5
time.Sleep(2 * time.Second)
}
上述结果输出5。和原程序结果不同的原因在于协程启动时需要保存上下文参数,程序B中协程启动入参为空,并引用ch;原程序启动先计算参数,然而计算参数时需要等待结果,当主协程准备往ch发送数据,也请求锁,造成死锁。
程序C
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
go func() {
fmt.Println(<-ch)
}()
time.Sleep(2 * time.Second)
}