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

在 Select 语句的默认情况下使用 runtime.Gosched() 是否有意义?

在 Select 语句的默认情况下使用 runtime.Gosched() 是否有意义?

Go
30秒到达战场 2022-12-19 20:31:42
Go的文档说Gosched 产生处理器,允许其他 goroutines 运行。它不会暂停当前的 goroutine,因此执行会自动恢复。基于该定义,如果我有一系列同时创建和执行的长时间运行的 go 例程,那么以下列方式编写 select 语句是否有利:for {    select {        case msg := <- msgch :             fmt.Println(msg)        default:             runtime.Gosched()    }} 我假设根据文档,这段代码会导致运行更多的 go 例程。我的假设正确吗?
查看完整描述

2 回答

?
catspeake

TA贡献1111条经验 获得超0个赞

不,这里没有必要,因为每当 Go 在等待通道或等待 I/O 时,它允许其他 goroutines 自动运行。自 Go 1.0 以来就是这种情况。

Go 1.2中,Go 运行时的调度程序会在您调用函数时添加自动抢占点。在此之前,如果你有一个 CPU 绑定循环(即使有一个函数调用),它可能会使调度程序饿死,你可能需要runtime.Gosched.

然后在Go 1.14中,他们使运行时的这方面变得更好,甚至没有函数调用的紧密 CPU 绑定循环也会自动被抢占。

因此,对于任何 Go 版本,您都不需要runtime.Gosched在等待通道或 I/O 时调用;在 1.14 之前,如果您正在进行长时间运行的计算,您可能想调用它。但是对于 Go 1.14+,我不明白为什么你需要手动调用它。


如果我正在审查您的实际代码,我建议将其更改为一个简单的for ... range循环:

for msg := range msgCh {
    fmt.Println(msg)
}

这将等待每条消息进入并打印它,如果/当通道关闭时停止。switch但是,如果您正在等待另一个通道或完成信号,例如上下文,您会想要一个。是这样的:

for {

    select {

        case msg := <- msgCh:

            fmt.Println(msg)

        case <-ctx.Done():

            return

    }

}


查看完整回答
反对 回复 2022-12-19
?
梦里花落0921

TA贡献1772条经验 获得超6个赞

使用runtime.Gosched()[anywhere] 有意义吗?

不。使用 Gosched 基本上不需要或不明智。


查看完整回答
反对 回复 2022-12-19
  • 2 回答
  • 0 关注
  • 99 浏览
慕课专栏
更多

添加回答

举报

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