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

发布于 2025-02-06 01:21:37 字数 376 浏览 1 评论 0原文

Go的文档说

gosched产生处理器,使其他goroutines可以运行。它不会暂停当前的goroutine,因此执行会自动恢复。

基于该定义,如果我有一系列长期运行的GO例程正在创建和同时执行,以下方式编写Select语句是有利的:

for {
    select {
        case msg := <- msgch : 
            fmt.Println(msg)
        default: 
            runtime.Gosched()
    }
} 

我假设基于文档,此代码可能会导致更多的GO例程正在运行。我的假设正确吗?

Go's documentation says that

Gosched yields the processor, allowing other goroutines to run. It does not suspend the current goroutine, so execution resumes automatically.

Based on that definition if I have a series of long running go routines being created and executed concurrently, would it be advantageous to write a select statement the following way:

for {
    select {
        case msg := <- msgch : 
            fmt.Println(msg)
        default: 
            runtime.Gosched()
    }
} 

I assume based on the documentation, this code can result in more go routines being run. Is my assumption correct?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

z祗昰~ 2025-02-13 01:21:38

不,这里不是必需的,因为每当GO在频道上等待或等待I/O时,它允许其他Goroutines自动运行。自从1.0以来就是这种情况。

go 1.2 时,Go Runtime的调度程序会添加自动preekimontion Preekimontion Preception点。在此之前,如果您有一个CPU结合的循环(即使使用函数调用)可能会饿死调度程序,并且您可能需要Runtime.gosched

然后在 go 1.14 中,他们使运行时的这一方面变得更好,甚至使得此方面变得更好无功能调用的紧密CPU循环会自动抢占。

因此,使用任何GO版本,您无需在频道或I/O上等待时调用runtime.gosched;在1.14之前,如果您要进行长期计算,您可能想打电话给它。但是使用GO 1.14+,我不知道为什么您需要手动称其为手动。


实际代码,我建议将其更改为简单的for ... ranga

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

如果我正在查看您的 频道关闭。但是,如果您在另一个频道或完成的信号(例如上下文)上等待switch。这样的事情:

for {
    select {
        case msg := <- msgCh:
            fmt.Println(msg)
        case <-ctx.Done():
            return
    }
}

No, it isn't necessary here, because whenever Go is waiting on a channel or waiting for I/O, it allows other goroutines to run automatically. That's been the case since Go 1.0.

In Go 1.2 the Go runtime's scheduler added automatic preemption points whenever you called a function. Prior to that if you had a CPU-bound loop (even with a function call) it could starve the scheduler and you might need runtime.Gosched.

And then in Go 1.14, they made this aspect of the runtime even better, and even tight CPU-bound loops with no functions calls are automatically pre-empted.

So with any Go version, you don't need to call runtime.Gosched when you're just waiting on a channel or on I/O; before 1.14, you may have wanted to call it if you were doing a long-running calculation. But with Go 1.14+, I don't see why you'd ever need to call it manually.


If I was reviewing your actual code, I'd suggest changing it to a simple for ... range loop:

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

This will wait for each message to come in and print it, and stop if/when the channel is closed. However, you would want a switch if you're waiting on another channel or done signal, for example a context. Something like this:

for {
    select {
        case msg := <- msgCh:
            fmt.Println(msg)
        case <-ctx.Done():
            return
    }
}
凉风有信 2025-02-13 01:21:38

使用runtime.gosched() [在任何地方]有意义吗?

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

Does using runtime.Gosched() [anywhere] make any sense?

No. It basically is never needed or sensible to use Gosched.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文