登录
首页 >  Golang >  Go问答

为什么当通道被阻塞时 select 语句会抛出错误

来源:stackoverflow

时间:2024-04-18 21:51:38 329浏览 收藏

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

问题内容

在此示例中,通道已满,因此 select 语句中的第一个 case 将阻塞,导致打印默认 case。或者至少我认为应该发生这样的事情。相反,我收到错误“所有 goroutine 都在睡觉 - 死锁!”。为什么是这样?我认为 select 语句会阻塞,直到其中一种情况可以运行,这是本例中的默认情况。

func main() {
        c := make(chan int)
        c <- 1
    
        select {
            case c <- 5:
                fmt.Println("a")
            default:
                fmt.Println("only case not blocked")
            // fatal error: all goroutines are asleep - deadlock!
    }
    }

解决方案


执行甚至没有到达 select 语句,因为它在此之前就陷入了死锁。您尝试发送到刚刚创建的通道,但它是无缓冲的 - 没有任何内容可供读取。所以程序死锁了,正确地告诉你所有的 goroutine 都被阻塞了。在选择之前删除发送,您将看到预期的行为。

通道是为 goroutine 通信而创建的。 当通道已满时,发送者等待另一个 goroutine 接收它。

无缓冲通道总是满的:必须有另一个 goroutine 来获取发送者发送的内容(同时)。

在这一部分中,您将写入通道:

c <- 1

这个也写入无缓冲通道,这会阻止它:

case c <- 5:

此示例基于您的代码来展示其工作原理:

package main

import (
    "fmt"
    "time"
)

func main() {
    c := make(chan int)
    go func() {
        fmt.Println(<-c) // starting goroutine and continuously reading from chan "c"
    }()

    time.Sleep(time.Millisecond) //to let goroutine start before program ends

    select {
    case c <- 5: // write into the channel so goroutine can read
        fmt.Println("a")
    default:
        fmt.Println("only case not blocked")
    }
    time.Sleep(time.Millisecond) //to let goroutine start before program finishes
}

理论要掌握,实操不能落!以上关于《为什么当通道被阻塞时 select 语句会抛出错误》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

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