为什么没有接收器被阻塞的错误?

根据Go 文档:


接收器总是阻塞直到有数据接收


此测试应该失败,因为对于来自通道的最后接收操作,没有相应的 write :


package main


import "fmt"


func main() {

    c := make(chan int)    

    for i := 0; i < 4; i++ { // 4 async reads

      go func() {

            fmt.Println("received:", <-c)

         }()


    }    

    // just 3 writes, 1 write is missing

    c <- 1   

    c <- 2 

    c <- 3   

}

但是脚本在读取 goroutine 中没有失败并显示错误消息,但它成功打印了 3 个值:


收到:1

收到:2

收到:3

为什么会这样,或者我对同步有误解?


噜噜哒
浏览 127回答 1
1回答

弑天下

这里没有死锁,因为maingoroutine 没有被阻塞。它发送 3 个c成功的值,因为有 4 个启动的 goroutine 从它接收,然后它结束。它也会结束你的应用程序,它不会等待其他非maingoroutine 结束。请参阅goroutine 无输出。死锁意味着所有 goroutine 都被阻塞。这不是这里的情况。尝试从没有人(当前或曾经)准备发送的通道接收不是错误。如果是事实,那是完全正常的。这是通道的用例之一:它充当同步工具,您可以发送/接收,并且操作将阻塞,直到另一端也准备好。在某些情况下,即使是在整个应用程序生命周期内阻塞的 goroutine 也是正常的,例如,goroutine 可能会等待用户输入(例如CTRL+ BREAK),用户可能永远不会按下并且应用程序可能会正常结束。所以这不被认为是错误,并且不会为这些打印错误或警告消息。但是如果你很好奇,它很容易实现。只需向您的函数添加一个延迟函数,该函数将在您的函数(以及您的应用程序)结束main()之前被调用。main()在该打印中运行的 goroutine 的数量:func main() {&nbsp; &nbsp; defer func() {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("Remaining goroutines:", runtime.NumGoroutine()-1) //-1 for main&nbsp; &nbsp; }()&nbsp; &nbsp; // your code}加上这个,输出将是:received: 1received: 2received: 3Remaining goroutines: 1如果您将循环更改为启动 14 个 goroutine 而不是 1 个,输出将显示剩余 11 个 goroutine。最后一点:由于在您的应用程序中,该main()函数不会等待其他 goroutine 结束,因此在调用延迟函数时它们可能仍然处于活动状态,因此它们可能会或可能不会包含在剩余的 goroutine 计数中。如果您使用 egsync.WaitGroup来等待它们结束,那么它们肯定不会被包括在内。有关示例,请参见在 Golang 中的 goroutines 完成之前阻止 main() 函数终止。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go