为了账号安全,请及时绑定邮箱和手机立即绑定

为什么有些频道操作会阻塞而有些不会

为什么有些频道操作会阻塞而有些不会

Go
陪伴而非守候 2022-06-01 17:28:04
我一直看到一些文章(和 golang 自己的文档)描述通道操作的方式与我在现实中看到的不一致。它与 Go 如何阻塞通道读/写有关。我现在在多个地方读到,当一个 goroutine 看到对通道的读取或写入时,它会阻止执行,这意味着它要么等待接收数据,要么等待另一个 goroutine 从通道接收数据。但是,如果您查看以下示例,这显然不是第二次写入发生的情况。package mainimport (    "fmt")func firstFunc(ch chan string) {    fmt.Println("firstFunc Hello", <-ch)    fmt.Println("firstFunc() carries on getting called")}func secondFunc(ch chan string) {    fmt.Println("secondFunc Hello", <-ch)    fmt.Println("secondFunc() carries on getting called")}func main() {    fmt.Println("main() started")    c1 := make(chan string)    c2 := make(chan string)    go firstFunc(c1)    go secondFunc(c2)    c1 <- "John"    c2 <- "Bob"    fmt.Println("main() ended")}这就是我解释 Go 执行此代码的方式:它打印 main() 开始的消息,创建通道 c1 和 c2 并将 firstFunc 和 secondFunc goroutine 排队(但此时不执行它们)它到达 c1 <- "John" 并阻止它,直到另一个 goroutine 从该通道读取此时它调度 firstFunc 从 c1 读取并继续执行其余代码直到函数结束main() 再次被重新安排,下一行是 C2 <- "Bob",此时我认为 main() 应该再次阻塞,就像它对 "John" 所做的那样,并等待 secondFunc 在继续之前从中读取。但这不是发生的事情。输出:main() startedfirstFunc Hello JohnfirstFunc() carries on getting calledmain() ended它不会简单地阻止对“Bob”的写入,而是继续执行直到 main() 完成并且从不调度 secondFunc。现在这已经成为我学习 Go 的一个障碍,因为我不确定是我不能信任的文章还是我的理解存在差距。我将不胜感激这方面的一些帮助。
查看完整描述

3 回答

?
红颜莎娜

TA贡献1842条经验 获得超13个赞

一个无缓冲的通道写入将阻塞,直到另一个 goroutine 从中读取。发生这种情况时,读取和写入 goroutine 都会启用。之后,无法保证执行将如何进行。

在您的示例中,firstFunc从通道读取后,它会运行直到完成。主 goroutine 写入通道 2,启用secondFunc,但在它有机会完成写入之前,主 goroutine 结束。

这里的问题是有许多可能的执行顺序,而您碰巧观察到一种特定的顺序。


查看完整回答
反对 回复 2022-06-01
?
largeQ

TA贡献2039条经验 获得超8个赞

您看不到输出,secondFunc因为 main 在它有机会执行之前就结束了。解决此问题的一种简单方法是time.Sleep(time.Second)在打印“main() 结束”之前添加。


更正确的方法是使用等待组,如下所示:


wg := sync.WaitGroup{}

wg.Add(2)

go func() { firstFunc(c1); wg.Done() }()

go func() { secondFunc(c2); wg.Done() }()

... // write to channels

wg.Wait() // This blocks till both the go-routines are done


查看完整回答
反对 回复 2022-06-01
?
长风秋雁

TA贡献1757条经验 获得超7个赞

它不会因为有 2 个通道侦听器(firstFunc 和 secondFunc)而阻塞。这些以随机顺序阅读您的消息(以先醒来者为准)。所以阻塞是存在的,但对于活跃的听众来说是无法观察到的。您唯一会看到的是,有时您会首先看到 firstFunc 的输出,有时您会看到 secondFunc 的输出



查看完整回答
反对 回复 2022-06-01
  • 3 回答
  • 0 关注
  • 146 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号