上文总结
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
go func() {
select {
case ch getVal, i= 1
getVal, i= 2
package main
import (
"fmt"
"time"
)
func talk(msg string, sleep int)
每次进入以下 select 语句时:
select {
case ch
<-input1< code> 和 <code><-input2< code> 都会执行,相应的值是:A x 和 B x(其中 x 是 0-5)。但每次 select 只会选择其中一个 case 执行,所以 <code><-input1< code> 和 <code><-input2< code> 的结果,必然有一个被丢弃了,也就是不会被写入 ch 中。因此,一共只会输出 5 次,另外 5 次结果丢掉了。(你会发现,输出的 5 次结果中,x 比如是 0 1 2 3 4)<!---input2<--></code><!---input1<--></code><!---input2<--></code><!---input1<-->
而 main 中循环 10 次,只获得 5 次结果,所以输出 5 次后,报死锁。
如果改为这样就一切正常:
select {
case t := <-input1: ch <- t case :="<-input2:" } < code></-input1:>
我的理解:
case ch <- <-input:< code>语句是分成两段执行的,可以理解为<!----->
t := <- input case选择还未明确的时候会执行 ch <- t 如果没有选择此case,则不执行此语句 并且这是两条语句,具有先后顺序 所以<-input 执行后,没有选择此case,<-input的结果就会被丢弃掉,从而导致上述的死锁问题。 < code></->
getVal, i= 1
getVal, i= 2
思考一:如果getVal()方法执行的时间不同,select的运行时长是取决于运行时间长的,还是时间的总和?
func getVal1(i int) int {
time.Sleep(time.Second * 1)
fmt.Println("getVal, i=", i)
return i
}
func getVal2(i int) int {
time.Sleep(time.Second * 2)
fmt.Println("getVal, i=", i)
return i
}
func main() {
ch := make(chan int)
go func() {
for {
beginTime := time.Now()
select {
case ch
输出的结果
getVal, i= 1
getVal, i= 2
3.0015862s
getVal, i= 1
getVal, i= 2
3.0021938s
getVal, i= 1
getVal, i= 2
3.0019246s
可以看出来,每次select都会按顺序执行case语句,并且select的执行时间为case语句的总和
当然在实际生产中也不会有这种写法
正确的写法:
func main() {
begin := time.Now()
ch := make(chan int)
ch2 := make(chan int, 2)
go func() {
ch2
输出结果,此时取决于运行时间最长的 getVal()
getVal, i= 1
1
getVal, i= 2
2
2.0020979s
在实际生产中,select语句只用于接受channel中的数值,而不是去执行某一方法
细心的小伙伴已经发现了,上述的写法有两个bug
加点注释看看输出的结果
func main() {
begin := time.Now()
ch := make(chan int)
ch2 := make(chan int, 2)
go func() {
ch2
输出的结果
getVal, i= 1
getVal, i= 2
goroutine num 2
1
2
2.0020965s
goroutine num 2
panic err send on closed channel
可以看到,for循环的协程并没有被释放,并且在后续的 ch <-< code>操作中也报出了panic异常<!---<-->
Original: https://www.cnblogs.com/xiaofua/p/15954405.html
Author: 小傅啊
Title: Go select 死锁引发的思考
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/516418/
转载文章受原作者版权保护。转载请注明原作者出处!