为了账号安全,请及时绑定邮箱和手机立即绑定

仅向通道发送值时进入工作流程

仅向通道发送值时进入工作流程

Go
有只小跳蛙 2023-06-19 15:49:20
当我只向通道发送值时,它会出错。这是示例代码。package mainimport "fmt"func main() {  ch := make(chan int)  ch <- 1  fmt.Println("Does not work")}在这里,我只是向通道发送值但没有收到任何东西。它给出一个错误fatal error: all goroutines are asleep - deadlock! 但是当我运行以下代码时,它不会给出任何错误package mainimport "fmt"func sum(s []int, c chan int) {    sum := 0    for _, v := range s {        sum += v    }    c <- sum // send sum to c}func main() {    s := []int{7, 2, 8, -9, 4, 0}    c := make(chan int)    go sum(s[:len(s)/2], c)    go sum(s[len(s)/2:], c)    fmt.Println("did not receive but still works")}并打印did not receive but still works我不明白为什么它在第二种情况下有效,而在第一种情况下却不起作用。即使在这两种情况下我都没有收到任何关于频道的价值。还有是什么导致了第一种情况下的死锁以及如何在第二种情况下避免死锁?
查看完整描述

1 回答

?
慕神8447489

TA贡献1780条经验 获得超1个赞

这两个例子都不起作用。事实上,在任何传统意义上的“工作”中,任何发送到通道的示例都不会工作。

但是,为了清楚起见,这是每个步骤的步骤:

第一个例子

ch := make(chan int)

这将创建一个无缓冲通道。无缓冲通道不保存任何数据,它们仅充当通信管道——在程序执行继续之前,所有发送的数据都必须由其他东西接收——在通道的任一侧。

ch <- 1

在这里,您在通道上发送数据,但没有等待接收它的东西,所以程序等待。在这种情况下,它会永远等待,因为您从未为该通道创建接收器,因此您会陷入僵局。

第二个例子

c := make(chan int)

同样,创建一个无缓冲通道。

go sum(s[:len(s)/2], c)

调用该sum函数,顺便说一句,由于上述原因,该函数也将永远阻塞——通道上没有接收任何东西,因此它将永远等待。但是,在这种情况下,您已经在 goroutine 中调用了它。goroutine 将在单独的执行线程中运行,而程序的其他部分运行。虽然,由于从不从通道接收数据,这个 goroutine 永远不会退出,直到主程序退出。

go sum(s[len(s)/2:], c)

再次,您sum在 goroutine 中一次又一次地调用。所以在这一点上,你有三个 gorotuines:一个运行main(),一个运行一个调用sum()。后两者永远不会退出。

然后你的程序退出。当程序退出时,所有 goroutines(包括永远卡在你的频道上的两个)退出。

由于该程序立即退出,因此永远不会报告死锁,但它确实存在,与您的第一个示例相同。


查看完整回答
反对 回复 2023-06-19
  • 1 回答
  • 0 关注
  • 133 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号