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

去例行阻止其他人

去例行阻止其他人

Go
Cats萌萌 2021-06-14 17:01:46
以下代码永远运行,而不是在开始后一秒停止。带有无限循环的 go 例程似乎阻止了另一个发送到超时通道。这是正常的吗? func main(){   timeout:=make(chan int)   go func(){      time.SLeep(time.Second)      timeout<-1    }()    res:=make(chan int)    go func(){        for{        }        res<-1    }()    select{        case<-timeout:            fmt.Println("timeout")        case<-res:            fmt.Println("res")    }}
查看完整描述

2 回答

?
SMILET

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

简短的回答:是的。

当前的实现使用 goroutines 之间的协作调度。这意味着一个 goroutine 必须将执行移交给调度程序,以便另一个 goroutine 运行。将来有希望使用不会有此限制的抢占式调度程序。

当以下任何一种情况发生时,Goroutines 将让给调度程序(可能不是一个完整的列表):

  • 无缓冲的 chan 发送/接收

  • 系统调用(包括文件/网络读写)

  • 内存分配

  • time.Sleep() 被调用

  • runtime.Gosched() 被调用

当您有一个非常处理器密集的循环时,最后一个允许您手动让步给调度程序。我从来没有发现需要它,因为我使用的几乎所有东西都有足够的通信(通道或系统 io),我的程序永远不会卡住。

还有 GOMAXPROCS,您可能会听到它作为解决方案。虽然它可以通过将所有 goroutine 放在不同的线程中来运行它们,但垃圾收集器最终会尝试运行并停止世界。当它停止世界时,不允许任何 goroutines 运行,如果高 cpu goroutines 永远不会让步,GC 将永远阻塞 goroutines 但永远不会运行。


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

添加回答

举报

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