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

入门教程:频道和缓冲频道

入门教程:频道和缓冲频道

Go
倚天杖 2021-04-08 09:27:31
当通过另一个go例程发送了第二个值并且没有接收到第一个发送的值时,为什么通道c没有缓冲出去?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)    x, y :=  <-c ,<-c// receive from c    fmt.Println(x,y ,x+y)}我期待的是一个错误-致命错误:所有goroutine都在睡着-死锁!当缓冲区已满时有一个块时,就会发生这种情况。由于通道c的大小为1,因此发送第二个值应该会产生上述错误。上面的代码中发生了什么?
查看完整描述

1 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

仅仅因为写入不能立即成功,只要有其他可以运行的goroutine,您就不会收到“死锁”错误。

让我们想象一下一个调度模型,其中一个go函数立即启动goroutine,并在屈服于他人之前尽其所能地向前推进。然后会发生这种情况:

  1. 该程序将调用sum()列表的前半部分,计算总和,然后尝试将其写入通道,但是由于没有侦听器,它将阻塞。

  2. 该程序将调用sum()列表的后半部分,计算总和,然后尝试将其写入通道,但是由于没有侦听器,它将阻塞。

  3. main() 会尝试从通道读取数据,唤醒之前的goroutine之一,并从中获取值。

  4. main() 将尝试从通道读取数据,唤醒另一个阻塞的goroutine,并从中获取值。

  5. 不再有人阻塞通道输入或输出,所有goroutine(包括main())都可以运行完毕。

如果您假装go只是在后台安排一些时间并继续运行主goroutine,则可以执行相同的练习。重要的是,一旦在同一通道上进行成对的读取和写入,两者都将继续进行。


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

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信