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

当我只向通道发送值时,它会出错。这是示例代码。

package main


import "fmt"


func main() {

  ch := make(chan int)

  ch <- 1


  fmt.Println("Does not work")

}

在这里,我只是向通道发送值但没有收到任何东西。它给出一个错误


fatal error: all goroutines are asleep - deadlock! 

但是当我运行以下代码时,它不会给出任何错误


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)


    fmt.Println("did not receive but still works")

}

并打印


did not receive but still works

我不明白为什么它在第二种情况下有效,而在第一种情况下却不起作用。即使在这两种情况下我都没有收到任何关于频道的价值。还有是什么导致了第一种情况下的死锁以及如何在第二种情况下避免死锁?


有只小跳蛙
浏览 139回答 1
1回答

慕神8447489

这两个例子都不起作用。事实上,在任何传统意义上的“工作”中,任何只发送到通道的示例都不会工作。但是,为了清楚起见,这是每个步骤的步骤:第一个例子ch&nbsp;:=&nbsp;make(chan&nbsp;int)这将创建一个无缓冲通道。无缓冲通道不保存任何数据,它们仅充当通信管道——在程序执行继续之前,所有发送的数据都必须由其他东西接收——在通道的任一侧。ch&nbsp;<-&nbsp;1在这里,您在通道上发送数据,但没有等待接收它的东西,所以程序等待。在这种情况下,它会永远等待,因为您从未为该通道创建接收器,因此您会陷入僵局。第二个例子c&nbsp;:=&nbsp;make(chan&nbsp;int)同样,创建一个无缓冲通道。go&nbsp;sum(s[:len(s)/2],&nbsp;c)调用该sum函数,顺便说一句,由于上述原因,该函数也将永远阻塞——通道上没有接收任何东西,因此它将永远等待。但是,在这种情况下,您已经在 goroutine 中调用了它。goroutine 将在单独的执行线程中运行,而程序的其他部分运行。虽然,由于从不从通道接收数据,这个 goroutine 永远不会退出,直到主程序退出。go&nbsp;sum(s[len(s)/2:],&nbsp;c)再次,您sum在 goroutine 中一次又一次地调用。所以在这一点上,你有三个 gorotuines:一个运行main(),一个运行一个调用sum()。后两者永远不会退出。然后你的程序退出。当程序退出时,所有 goroutines(包括永远卡在你的频道上的两个)退出。由于该程序立即退出,因此永远不会报告死锁,但它确实存在,与您的第一个示例相同。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go