如何向golang初学者解释通道阻塞机制?

我是一个golang初学者,在学习频道和日常工作时遇到了一些麻烦。我的一个卡住点是golang通道阻止机制是如何工作的。在golang tour中,它说我用我的理解做了一些实验,并达到了结果,.这些提示并没有真正让我对错误是如何发生的了解。我用谷歌搜索过它,但我得到的几乎每篇文章都是关于渠道的深层机制,或者它假设读者理解了单个单词已经给出了所有的信息。By default, sends and receives block until the other side is ready.fatal error: all goroutines are asleep - deadlock!block

但作为一个初学者,我有很多疑问,比如:

  • 同一 go-routine 能否在写入通道后执行通道读取操作?

  • 如果某个通道被阻塞,其他 go-routine 还能向它发送消息吗?

  • 如果 go-routine 尝试将消息发送到被阻止的通道,会发生什么情况?它会通过错误,还是什么也没发生,或者?

以下是我的一个让我感到困惑的测试?(据我所知,main func是一个go-routine,我认为它的执行是相同的)

package main


import "time"


func chanWrite(s string, ch chan string) {

    ch <- s

    println("write", s)

}


func chanRead(ch chan string) {

    println("read", <- ch)

}


// main func 1

func main() {

    ch := make(chan string)

    go chanWrite("A", ch)

    time.Sleep(time.Second)

}


// main func 1 didn't throw error



// main func 2(modify main func 1 and then execute it)

func main() {

    ch := make(chan string)

    chanWrite("A", ch)

    time.Sleep(time.Second)

}

// main func 2 throw error: "fatal error: all goroutines are asleep - deadlock!"


我在这个测试中看到的是在某些情况下,当我在没有阅读的情况下将内容写入通道时,我得到了,有时什么也没发生(例如在main func 1中)。fatal error


那么,有人可以以一种简单而深入的方式解释通道块是如何工作的,以便golang初学者可以轻松理解它吗?


泛舟湖上清波郎朗
浏览 73回答 2
2回答

慕的地6264312

goroutine 可以阻止等待通道准备好发送或接收,但通道本身永远不会处于“阻塞”状态。第一个程序不会死机,因为 main 函数执行到最后并终止程序。同一 go-routine 能否在写入通道后执行通道读取操作?否,如果通道未缓冲(默认值)。对于无缓冲信道,发送 goroutine 会阻塞,直到接收 goroutine 准备就绪。单个 goroutine 不能同时执行发送和接收。如果只有一个 goroutine 发送到通道,则 goroutine 会永远阻塞。如果某个通道被阻塞,其他 go-routine 还能向它发送消息吗?goroutine 可以在通道关闭之前的任何时间将值发送到通道。Goroutine 可以阻止等待通道准备好发送。如果 go-routine 尝试将消息发送到被阻止的通道,会发生什么情况?它会通过错误,还是什么也没发生,或者?Goroutine可以阻止等待频道准备就绪。通道本身未处于阻塞状态。

撒科打诨

通道不会“阻塞”。通道上的读取或写入操作可能会阻塞。对于无缓冲通道(这是您上面的内容):写入操作将阻止写入 goroutine,直到另一个 goroutine 准备好从该通道读取。当读取 goroutine 准备好读取(即执行 <-ch)时,则写入和读取发生,并且两个 goroutine 继续运行。对于缓冲通道:只要通道缓冲区未满,写入操作就不会阻塞。同样,如果有要从通道读取的内容,则读取不会阻塞。至于你的问题:如果所讨论的通道未缓冲,则写入操作将阻塞,因为只有当另一个 goroutine 正在从该通道读取时,写入操作才能继续。因此,goroutine不会进展为从通道读取。如果这是一个缓冲通道,并且通道未满,则相同的 goroutine 可以写入该通道并从中读取。如果一个 goroutine 正在等待写入一个通道,而另一个 goroutine 来写入它,它也会阻塞,直到另一个 goroutine 从通道读取。如果 goroutine 尝试写入已满的通道,它将阻塞,直到另一个 goroutine 可以从该通道读取。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go