当前位置:  首页>> 技术小册>> GO面试指南

在 Go 中,有一些操作会触发 runtime 调度,包括:

  • 阻塞操作:比如通道的读写、休眠、等待 I/O 完成等。
  • GC:当 Go 运行时需要回收垃圾时,也会触发调度器的运行。
  • 系统调用:因为 Go 运行时在底层使用了线程和协程,所以当系统调用需要等待 I/O 操作完成时,调度器会将当前线程放入等待队列,然后切换到另一个线程上继续执行。
  • 用户调用 runtime.Gosched() 函数:这个函数可以手动触发调度器的运行,让当前 goroutine 主动让出 CPU 给其他 goroutine 使用。

下面是一个示例代码,演示了阻塞操作和手动调用 runtime.Gosched() 函数会触发调度器的运行:

  1. package main
  2. import (
  3. "fmt"
  4. "time"
  5. )
  6. func main() {
  7. go func() {
  8. for i := 0; i < 10; i++ {
  9. fmt.Println("goroutine 1:", i)
  10. time.Sleep(100 * time.Millisecond) // 阻塞操作
  11. }
  12. }()
  13. go func() {
  14. for i := 0; i < 10; i++ {
  15. fmt.Println("goroutine 2:", i)
  16. time.Sleep(100 * time.Millisecond) // 阻塞操作
  17. }
  18. }()
  19. for i := 0; i < 10; i++ {
  20. fmt.Println("main goroutine:", i)
  21. if i == 5 {
  22. runtime.Gosched() // 手动触发调度器运行
  23. }
  24. }
  25. }

在这个示例代码中,我们启动了两个 goroutine,每个 goroutine 都会执行一段循环并进行阻塞操作。同时,主 goroutine 也会执行一段循环,并在第 5 次迭代时手动调用 runtime.Gosched() 函数。

由于每个 goroutine 的循环都进行了阻塞操作,所以它们会在运行一段时间后自动让出 CPU 给其他 goroutine 使用。

另外,当主 goroutine 调用了 runtime.Gosched() 函数时,它也会主动让出 CPU 给其他 goroutine 使用。这些操作都会触发调度器的运行,让所有 goroutine 在执行过程中公平地分享 CPU 时间。


该分类下的相关小册推荐: