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

为什么程序会在select中被频道阻塞?

为什么程序会在select中被频道阻塞?

Go
米脂 2022-10-17 10:16:22
package mainimport (    "fmt")type A struct{    exit chan bool}func (a *A) f(){    select{        //the routine process        //quit        case <- a.exit:                fmt.Println("-----over-----")                a.exit <- true                fmt.Println("+++++over++++++")                      }}func main() {    a := A{}        go a.f()    a.exit = make(chan bool)        a.exit <- true}我想运行多协程,我想让主函数注意到其他协程退出。这是我的代码,但是选择中的程序块,程序只输出“-----over-----”,没有“+++++over++++++”,代码有什么问题?感谢您帮助。
查看完整描述

1 回答

?
芜湖不芜

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

您的程序阻塞,因为这是您编写的,请考虑以下操作顺序:

  1. maingoroutine 启动a.fgoroutine。

  2. a.f试图从 nil 通道读取的块a.exit

  3. main设置a.exit为无缓冲通道,a.f现在阻止从新通道读取,这是允许的。

  4. main将值写入a.exita.f从中读取值a.exit,这会同步 goroutines,现在下界被阻塞。

  5. a.f现在阻止尝试写入 unbuffered a.exit,这将永远不会解除阻止,因为没有人会再次尝试从通道读取。

  6. main现在退出并导致所有其他 goroutine 退出,这可能发生在第 5 步之前。

所以你的程序从不输出的原因+++++over++++++是:

  • 你的a.fgoroutine 阻塞,a.exit <- true因为没有其他 goroutine 会从通道中读取这个值。

  • 您的goroutine 可能会在完成工作main之前退出并终止整个程序。a.f

我想你是在问如何在 goroutine 完成后让 main 退出,这是最简单的例子:

package main


import (

    "fmt"

)


type A struct {

    exit chan struct{}

}


func (a *A) f() {

    defer close(a.exit) // Close the chanel after f() finishes, closed channels yield the zero-value so <-a.exit will unblock


    fmt.Println("+++++over++++++")

}


func main() {

    a := A{}

    go a.f()

    a.exit = make(chan struct{})


    <-a.exit

}


查看完整回答
反对 回复 2022-10-17
  • 1 回答
  • 0 关注
  • 70 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信