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

Go并发和通道混淆

Go并发和通道混淆

Go
拉丁的传说 2021-06-25 09:07:05
我是 Go 的新手,在理解并发和通道时遇到了问题。package mainimport "fmt"func display(msg string, c chan bool){    fmt.Println("display first message:", msg)    c <- true}func sum(c chan bool){    sum := 0    for i:=0; i < 10000000000; i++ {        sum++    }    fmt.Println(sum)    c <- true}func main(){    c := make(chan bool)    go display("hello", c)    go sum(c)    <-c}程序的输出是:display first message: hello10000000000 但我认为它应该只有一行:display first message: hello所以在主函数中,<-c 正在阻塞它并等待其他两个 go 例程向通道发送数据。一旦主函数从 c 接收到数据,它应该继续并退出。display 和 sum 同时运行并且 sum 需要更长的时间,因此 display 应该向 c 发送 true 并且程序应该在 sum 完成之前退出...我不确定我是否理解清楚。有人可以帮我解决这个问题吗?谢谢!
查看完整描述

1 回答

?
守着星空守着你

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

程序的确切输出未定义,取决于调度程序。调度器可以在当前未被阻塞的所有 goroutine 之间自由选择。它试图通过在非常短的时间间隔内切换当前 goroutine 来同时运行这些 goroutine,以便用户感觉一切都是同时发生的。除此之外,它还可以在不同的 CPU 上并行执行多个 goroutine(如果您碰巧有一个多核系统并增加runtime.GOMAXPROCS)。可能导致您输出的一种情况是:

  1. main 创建两个 goroutine

  2. 调度器选择立即切换到新的 goroutine 之一并选择 display

  3. display打印出消息并被通道 send ( c <- true)阻塞,因为还没有接收器。

  4. 调度程序选择sum下一个运行

  5. 总和被计算并打印在屏幕上

  6. 调度程序选择不恢复sumgoroutine(它已经使用了相当多的时间)并继续执行display

  7. display 将值发送到通道

  8. 调度程序选择接下来运行 main

  9. main 退出,所有 goroutine 都被销毁

但这只是一种可能的执行顺序。还有很多其他的,其中一些会导致不同的输出。如果您只想打印第一个结果然后退出程序,您可能应该使用 aresult chan string并将您的main功能更改为 print fmt.Println(<-result)


查看完整回答
反对 回复 2021-06-28
  • 1 回答
  • 0 关注
  • 192 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

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

帮助反馈 APP下载

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

公众号

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