繁体   English   中英

通道何时阻止goroutine

[英]When does a channel block a goroutine

如果我定义了一个没有缓冲区的通道并向其中写入一个数据,它会立即阻塞吗(以便内核将寻找从该通道读取的另一个不受阻塞的goroutine),或者它会继续执行并在下次某些代码尝试时阻塞在尚未读取该通道时再次写入该通道?

以下是我编写的用于研究此问题的两段代码。

代码1:

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)
    }
}

输出是这样的:

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,因为已打印“将0插入通道”。

代码2:

package main

import "fmt"

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

由于在运行时报告了死锁错误,所以这段代码无法正确运行。

fatal error: all goroutines are asleep - deadlock!

在我看来,执行c <-2时,goroutine被阻止(如果未阻止,则将执行fmt.Println行,而继续执行将在<-c处解锁c)。 阻止此goroutine时,内核将搜索其他goroutine,但均未找到,因此将报告死锁错误。

总之,在第一段代码中,我得出结论,写到通道不会立即阻止goroutine,但是从第二段代码中会阻止。 我在哪里弄错了,通道什么时候会阻塞goroutine?

发送到没有可用缓冲区空间的通道会阻塞发送方,直到发送完成为止。 从没有可用消息的信道接收将阻塞接收器,直到接收完成。 未缓冲的通道永远不会有缓冲空间-发送块直到有东西接收为止,反之亦然。 围棋之旅涵盖了这一点: https : //tour.golang.org/concurrency/2

请记住,您的代码是并发的,因此您不能过多地理解输出语句的顺序。 在发送/接收操作和将消息打印到标准输出之间时,可以使goroutine处于睡眠状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM