登录
首页 >  Golang >  Go问答

问题会发生在缓冲和非缓冲通道上

来源:stackoverflow

时间:2024-02-22 19:03:23 328浏览 收藏

积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《问题会发生在缓冲和非缓冲通道上》,就带大家讲解一下知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~

问题内容

我对 go 中缓冲通道和非缓冲通道之间的区别有点困惑。例如,下面的代码执行良好:

package main

import "fmt"

func main() {
    messages := make(chan string)
    go func() { messages <- "ping" }()
    msg := <-messages
    fmt.println(msg)
}

另一方面,当我将 "ping" 传递给常规函数中的消息时,会出现死锁。

package main

import "fmt"

func main() {
    messages := make(chan string)
    func() { messages <- "ping" }()
    msg := <-messages
    fmt.println(msg)
}

最后,当我使用缓冲通道时,这个问题就得到了解决,就像这样

package main

import "fmt"

func main() {
    messages := make(chan string, 1)
    func() { messages <- "ping" }()
    msg := <-messages
    fmt.Println(msg)
}

我很困惑为什么第二个案例失败了。举例说明

默认情况下,通道是无缓冲的,这意味着如果有相应的接收 (<-chan) 准备好接收发送的值,它们只会接受发送 (chan <-)。缓冲通道接受有限数量的值,而没有这些值的相应接收器。

在这三种情况下,msg 不是 messages 的接收器吗?


解决方案


如果不读取未缓冲的通道,则会阻塞。缓冲通道在达到容量之前不会阻塞。

您的第一个示例实际上启动了一个单独的 go 例程,该例程执行尝试将“ping”写入消息通道的函数。它将阻塞,直到从消息通道读取的语句执行为止。由于该函数位于单独的 goroutine 上,因此能够命中从消息通道读取的语句。

您的第二个示例声明并调用一个尝试写入消息通道的函数,但该通道永远不会准备好写入,因为您正在同一主执行线程上执行。从消息通道读取的语句永远不会命中,因为您在写入通道时被阻止。

第三个示例,通道被缓冲并且可以写入,因为它在阻塞之前可以接受 1 个值。

在第一个示例中,从另一个 goroutine 调用嵌套函数。该函数开始运行并阻塞等待写入通道。主 Goroutine 也会运行,并从通道读取数据,释放第二个 Goroutine 中的块。

在第二个示例中,嵌套函数由 main 调用,并且 main 等待它返回。由于通道没有缓冲,所以写操作会阻塞,这意味着主goroutine被阻塞并且没有其他goroutine,因此死锁。

在第三个示例中,通道被缓冲,因此第一次写入不会阻塞。

今天关于《问题会发生在缓冲和非缓冲通道上》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>