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

当通过另一个go例程发送了第二个值并且没有接收到第一个发送的值时,为什么通道c没有缓冲出去?


package main

import "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,因此发送第二个值应该会产生上述错误。


上面的代码中发生了什么?


倚天杖
浏览 240回答 1
1回答

幕布斯6054654

仅仅因为写入不能立即成功,只要有其他可以运行的goroutine,您就不会收到“死锁”错误。让我们想象一下一个调度模型,其中一个go函数立即启动goroutine,并在屈服于他人之前尽其所能地向前推进。然后会发生这种情况:该程序将调用sum()列表的前半部分,计算总和,然后尝试将其写入通道,但是由于没有侦听器,它将阻塞。该程序将调用sum()列表的后半部分,计算总和,然后尝试将其写入通道,但是由于没有侦听器,它将阻塞。main()&nbsp;会尝试从通道读取数据,唤醒之前的goroutine之一,并从中获取值。main()&nbsp;将尝试从通道读取数据,唤醒另一个阻塞的goroutine,并从中获取值。不再有人阻塞通道输入或输出,所有goroutine(包括main())都可以运行完毕。如果您假装go只是在后台安排一些时间并继续运行主goroutine,则可以执行相同的练习。重要的是,一旦在同一通道上进行成对的读取和写入,两者都将继续进行。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go