当通过另一个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,并在屈服于他人之前尽其所能地向前推进。然后会发生这种情况:
该程序将调用
sum()
列表的前半部分,计算总和,然后尝试将其写入通道,但是由于没有侦听器,它将阻塞。该程序将调用
sum()
列表的后半部分,计算总和,然后尝试将其写入通道,但是由于没有侦听器,它将阻塞。main()
会尝试从通道读取数据,唤醒之前的goroutine之一,并从中获取值。main()
将尝试从通道读取数据,唤醒另一个阻塞的goroutine,并从中获取值。不再有人阻塞通道输入或输出,所有goroutine(包括
main()
)都可以运行完毕。
如果您假装go
只是在后台安排一些时间并继续运行主goroutine,则可以执行相同的练习。重要的是,一旦在同一通道上进行成对的读取和写入,两者都将继续进行。
- 1 回答
- 0 关注
- 239 浏览
添加回答
举报
0/150
提交
取消