关于golang:Goroutine调度器及面试精选

42次阅读

共计 1026 个字符,预计需要花费 3 分钟才能阅读完成。

Goroutine 调度器

Go 语言在并发编程有着十分弱小的能力,讲到调度器,咱们的话题离不开操作系统、过程与线程这些概念,在学习操作系统时,线程是操作系统调度的最根本单元。

在没有学习 Go 语言之前,线程之间通信,通过内存共享能够实现,然而在调度时每个线程都会占用 1M 以上内存空间,还有复原寄存器中内容也须要向操作系统申请或销毁资源,这样会有较大额定开销。

在 Go 语言中,不须要通过共享内存来通信,而是通过通信来共享内存,这也是 Go 语言最重要的编程理念。这样的话,Go 调度器对 Goroutine 的上下文切换就缩小额定开销了。

Go 调度器概念

  • G(Goroutine) — 示意 Go 协程,它是一个待执行的工作或代表一个 Goroutine 对象;
  • M(Machine) — 示意操作系统的线程,它由操作系统的调度器调度和治理;
  • P(Processor) — 示意处理器,它能够被看做运行在线程上的本地调度器;

M 必须领有 P 才能够执行 G 中的代码,P 含有一个蕴含多个 G 的队列,P 能够调度 G 交由 M 执行。 P 的个数在启动时就决定,默认是应用等同 CPU 的数量,又因为 M 必须持有一个 P 能力运行 Go 代码,所有 M 个数个别也是等同于 CPU 个数,以达到尽可能的应用 CPU 而又不至于产生过多的线程切换开销,这样就大大降低操作系统和硬件的负载。P 的个数,能够应用 runtime.GOMAXPROCS() 来设置个数,当在 IO 密集的场景下能够自行设置来进步性能。

Go 语言的调度器是一个非常复杂机制,看了 Go 源码,尽管有很多正文,然而对于工作经验不足或刚入门 Go 开发来说,咱们还是须要多多的深钻研,还有很多细节须要去学习,比方,调度器的设计原理:

  • 在早起 0.x 版本中 Go 语言调度器是单线程调度器,由 G - M 模型组成,还有 P 这个概念;
  • 通过一直优化与设计,到 1.0 版本就引入多线程调度器,然而呈现全局锁导致竞争重大;
  • 到 1.1 版本,引入处理器 P,而后就形成 GMP 模型;
  • 到 Go 1.2 退出抢占式调度器;以及到 1.14 版本引入基于信号量的抢占式调度器

面试题:

  1. Go 中的 GMP 模型理解吗?
  2. GMP 模型 Go 有几种状态?(闲暇、待运行、运行中、零碎调用、期待中、已进行及栈复制中)
  3. 为什么 Go 能进步性能,与过程和线程有什么区别?

    • 线程和过程会导致 CPU 额定开销大,切换线程上下文及申请销毁都须要额定开销;
    • 线程占用内存个别是固定为 2M 内存空间;
    • Go 栈内存是可变的,初始的时候个别为 2KB,最大可扩大为 1GB;
    • Go 本人实现的调度器,所以创立和销毁开销小;
正文完
 0