Golang中runtime.Gosched的使用问题探讨
Golang中runtime.Gosched的使用问题探讨 大家好,
对于 runtime.Gosched 还不太理解。以下是 go doc 显示的内容。那么当我在 goroutine 中执行 runtime.Gosched() 时,它会将处理器让给其他 goroutine 运行,同时它自己是否仍会继续运行?有没有什么好的示例可以让我尝试?谢谢
(base) zwang-mac:cmd2 zwang$ go doc runtime.Gosched
func Gosched()
Gosched yields the processor, allowing other goroutines to run. It does not
suspend the current goroutine, so execution resumes automatically.
更多关于Golang中runtime.Gosched的使用问题探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html
jameswang2015:
那么当我在goroutine中执行runtime.Gosched()时,它会把处理器让给其他goroutine运行
简单来说,并发不等于并行。在多核处理器(如i3、i5等)上,调度goroutine并不简单意味着两个核心同时运行main和goroutine进程(那是并行)。因此,main和goroutine共享同一个处理核心,以看似并行工作的方式运行(这才是并发)。
由于main和goroutine共享同一个处理核心,goroutine之间(注意:main本身也是一个goroutine)经常会发生核心切换。这就是为什么需要提供runtime.Gosched()。
请注意,如果您的并发代码经过良好规划和执行(例如妥善处理通道I/O),您很少需要调用runtime.Gosched()。
jameswang2015:
有没有可以尝试的好例子?谢谢
您可以尝试使用互斥锁重新实现Go中的通道功能。这可能很浪费时间,但这是我之前见过它使用的一个案例。
更多关于Golang中runtime.Gosched的使用问题探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,runtime.Gosched() 是一个用于主动让出处理器(P)给其他goroutine运行的函数。根据官方文档说明,调用Gosched()不会挂起当前goroutine,而是暂时让出执行机会,但当前goroutine仍处于可运行状态,之后会被调度器重新调度执行。
关键点解释:
- 让出处理器:当前goroutine主动放弃占用的处理器时间片,允许其他就绪的goroutine运行。
- 不挂起goroutine:当前goroutine不会进入阻塞状态,而是被放回全局运行队列,等待下次调度。
- 自动恢复执行:调度器会在后续的某个时间点自动恢复该goroutine的执行。
示例代码:
以下示例演示了runtime.Gosched()的行为。我们创建两个goroutine,其中一个频繁调用Gosched()来让出处理器,观察它们的执行顺序变化。
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
var wg sync.WaitGroup
wg.Add(2)
// Goroutine 1: 频繁调用 Gosched
go func() {
defer wg.Done()
for i := 0; i < 5; i++ {
fmt.Printf("Goroutine 1: %d\n", i)
runtime.Gosched() // 让出处理器,给其他goroutine机会
}
}()
// Goroutine 2: 不调用 Gosched
go func() {
defer wg.Done()
for i := 0; i < 5; i++ {
fmt.Printf("Goroutine 2: %d\n", i)
}
}()
wg.Wait()
}
运行结果分析:
多次运行此程序,输出顺序可能不同。由于Goroutine 1在每次循环中调用runtime.Gosched(),它会更频繁地让出处理器,导致Goroutine 2有更多机会执行。典型输出可能如下(顺序可能变化):
Goroutine 1: 0
Goroutine 2: 0
Goroutine 2: 1
Goroutine 1: 1
Goroutine 2: 2
Goroutine 1: 2
...
进一步测试示例:
以下示例更明确地展示了Gosched()的效果,通过一个长时间运行的goroutine来观察让出行为:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
// 设置使用1个处理器,便于观察调度行为
runtime.GOMAXPROCS(1)
go func() {
for i := 0; i < 3; i++ {
fmt.Printf("Without Gosched: %d\n", i)
}
}()
go func() {
for i := 0; i < 3; i++ {
fmt.Printf("With Gosched: %d\n", i)
runtime.Gosched()
}
}()
// 等待goroutine执行
time.Sleep(time.Second)
}
在这个示例中,由于设置了GOMAXPROCS(1),只有一个处理器可用。调用Gosched()的goroutine会主动让出处理器,使得另一个goroutine能够插入执行。
总结:runtime.Gosched()是一种协作式调度手段,适用于调试或特定场景下的公平性调整,但在生产代码中应谨慎使用,因为Go调度器通常能自动高效地管理goroutine执行。

