golang管道channel顺序执行报错deadlock

5 篇文章 0 订阅

当golang顺序执行时,会报错
fatal error: all goroutines are asleep - deadlock!

package main
import (
    "fmt"
)
func main() {
    ch := make(chan int)
    ch<-1
    c1 :=<-ch
    fmt.Println(c1)
}

不知道有没有跟我一样好奇,为什么下面读取了管道的内容,还是会报错呢,其实这样是因为对主程main而言,到ch<-1时,无法知道下面是否管道有读取数据,所以就会阻塞报错,可以在ch<-1上面加个go协程来处理,这也是为什么go协程写到ch<-1下面会报错的原因(当然用非阻塞也可以解决)
这么解释获取更专业一点:
通道ch在写入时,是同步等待接收端接收的状态,而接收的代码却在下一行,这个时候就导致了整个程序无法往下执行,造成死锁
解决方案:
起一个协程,使接受数据和发送数据并行执行
正确写法:

package main
import (
    "fmt"
)
func main() {
    ch := make(chan int)
    go t1(ch)
    ch<-1
}
func t1(ch chan int){
    fmt.Println("协程开始")
    c1 :=<-ch
    fmt.Println(c1)
}

注意下面这个go t1()位置,是错误的,原因就是main无法判断下面是否有管道ch数据读取

package main
import (
    "fmt"
)
func main() {
    ch := make(chan int)
    ch<-1
    go t1(ch) //ERROR:不可写在ch<-1后面
}
func t1(ch chan int){
    fmt.Println("协程开始")
    c1 :=<-ch
    fmt.Println(c1)
}

当然也可以给管道ch增加缓存区后,这样数据暂存到缓冲区,就不需要接收端同时接收数据了

//这个会阻塞报错锁错误(传的是<-ch1 此时已做了计算)
//一位同事说过:数传can,参数会优先计算结果放到堆栈里的
//另一位同事说:入参要先求值(个人觉得这个比较好理解)
func main() {
ch1 := make(chan int)
go fmt.Println(<-ch1)
ch1 <- 5
time.Sleep(1 * time.Second)
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值