首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通道何时会阻塞goroutine

通道何时会阻塞goroutine
EN

Stack Overflow用户
提问于 2019-06-21 23:38:47
回答 1查看 1.5K关注 0票数 1

如果我定义了一个没有缓冲区的通道,并将一个数据写入其中,它是立即阻塞(这样内核将寻找另一个未阻塞的goroutine,从该通道读取数据),还是继续执行,并在下一次某些代码再次尝试写入通道时阻塞(当它还没有被读取时)?

下面是我用来研究这个问题的两段代码。

code1:

代码语言:javascript
复制
package main

import "fmt"

func main() {
    c := make(chan int)
    go func() {
        for i := 0;i < 3; i++ {
            c <- i
            fmt.Printf("number %v inserted into channel\n", i)
        }
    }()
    for i := 0; i < 3; i++ {
        fmt.Printf("number poped from channel %v\n", <-c)
    }
}

输出如下所示:

代码语言:javascript
复制
number 0 inserted into channel
number poped from channel 0
number poped from channel 1
number 1 inserted into channel
number 2 inserted into channel
number poped from channel 2

在第一次写入c之后,这个goroutine似乎会继续执行,因为"number 0 inserted into channel“已经打印出来了。

code2:

代码语言:javascript
复制
package main

import "fmt"

func main() {
    c := make(chan int)
    c <- 2
    fmt.Println("Something is written into channel")
    <-c
}

这段代码无法正确运行,因为在运行时会报告死锁错误。

代码语言:javascript
复制
fatal error: all goroutines are asleep - deadlock!

在我看来,当c <-2被执行时,goroutine被阻塞(如果它没有被阻塞,fmt.Println行将被执行,继续执行将在<-c处解锁c)。当这个goroutine被阻塞时,内核会搜索其他goroutine,但是没有找到,所以它会报告一个死锁错误。

总而言之,在第一段代码中,我得出结论,写入通道不会立即阻塞goroutine,但从第二段代码开始会阻塞goroutine。我哪里搞错了,什么时候通道阻塞了goroutine?

EN

回答 1

Stack Overflow用户

发布于 2019-06-21 23:40:30

发送到没有可用缓冲区空间的通道会阻止发送方,直到发送可以完成;从没有可用消息的通道接收会阻止接收方,直到接收可以完成。未缓冲的通道永远不会有缓冲空间--在接收到数据之前发送数据块,反之亦然。这在Go之旅中有所介绍:https://tour.golang.org/concurrency/2

请记住,您的代码是并发的,因此您不能从输出语句的顺序中读取太多内容。在发送/接收操作之间以及将消息打印到stdout时,可以将goroutine置于睡眠状态。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56706566

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档