gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 22:31:12 25 4
gpt4 key购买 nike

根据Go documentation :

Receivers always block until there is data to receive



此测试应该失败,因为对于来自 channel 的最后接收操作,没有相应的 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

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

最佳答案

这里没有死锁,因为 main goroutine 没有被阻塞。它在 c 上发送 3 个值成功是因为有 4 个已启动的 goroutine 从它接收,然后它结束。并且它也会结束您的应用程序,它不会等待其他非 main goroutines 结束。见 No output from goroutine .

死锁意味着所有 goroutine 都被阻塞。这不是这里的情况。

尝试从没有人(当前或曾经)准备发送的 channel 接收不是错误。如果是事实,那是完全正常的。这是 channel 的用例之一:它充当同步工具,您可以发送/接收,并且操作将阻塞,直到另一端也准备好。

在某些情况下,甚至在整个应用程序生命周期中阻塞的 goroutine 也是正常的,例如goroutine 可能会等待用户输入,例如 CTRL+BREAK,用户可能永远不会按下它,应用程序可能会正常结束。

所以这不被认为是错误,并且不会为这些打印错误或警告消息。但是如果你很好奇,它很容易实现。只需将延迟函数添加到您的 main()这将在您的 main() 之前被称为最后一件事功能(以及您的应用程序)结束。在该打印中运行的 goroutine 的数量:

func main() {
defer func() {
fmt.Println("Remaining goroutines:", runtime.NumGoroutine()-1) //-1 for main
}()

// your code
}

加上这个,输出将是:
received: 1
received: 2
received: 3
Remaining goroutines: 1

如果您将循环更改为启动 14 个 goroutine 而不是 1 个,输出将显示剩余 11 个 goroutine。

最后一点:因为在您的应用程序中, main()函数不会等待其他 goroutines 结束,它们可能在调用延迟函数时仍然处于事件状态,因此它们可能会或可能不会包含在剩余的 goroutines 计数中。如果你会使用例如 sync.WaitGroup等他们结束,那么他们肯定不会被包括在内。见 Prevent the main() function from terminating before goroutines finish in Golang例如。

关于go - 为什么没有接收器被阻塞的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59750056/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com