MST

星途 面试题库

面试题:Go中Goroutine调度机制的M:N模型简述

请简要描述Go语言中Goroutine调度采用的M:N模型,包括M、N分别代表什么,以及这种模型的优势和实现要点。
46.1万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

M:N模型概述

在Go语言的Goroutine调度中,M:N模型指的是N个用户级线程(Goroutine)映射到M个内核级线程(OS线程)。

M、N代表的含义

  • M:代表内核级线程(OS线程)。每个M都由操作系统调度,拥有自己的栈空间、寄存器等资源。在Go语言中,M由runtime管理,Go运行时通过系统调用向操作系统获取M。
  • N:代表用户级线程,也就是Goroutine。Goroutine非常轻量级,它们由Go运行时的调度器管理,共享M的资源。一个Goroutine有自己的栈、程序计数器和局部变量等,但其栈在运行过程中可以动态增长和收缩。

优势

  1. 高并发能力:由于Goroutine非常轻量级,允许在一个程序中创建大量的Goroutine,轻松实现高并发。相比传统的线程模型,创建和销毁Goroutine的开销极小,使得系统可以支持海量并发任务。
  2. 资源利用率高:M:N模型可以复用少量的内核线程来运行大量的Goroutine,减少了内核线程的数量,降低了上下文切换的开销。同时,Goroutine的栈空间按需增长和收缩,进一步提高了内存的利用率。
  3. 调度灵活:Go运行时的调度器在用户态实现了自己的调度算法,对Goroutine的调度更加灵活。例如,调度器可以在Goroutine阻塞时,将其从当前M上摘除,并在合适的时候重新调度到其他M上运行,而不需要依赖操作系统的调度机制。

实现要点

  1. Goroutine队列:Go运行时维护多个Goroutine队列,包括全局队列和每个M对应的本地队列。新创建的Goroutine首先被放入全局队列,M在运行过程中优先从本地队列获取Goroutine来执行,如果本地队列为空,则从全局队列或其他M的本地队列窃取Goroutine。
  2. 调度器:Go的调度器(runtime scheduler)负责管理Goroutine的生命周期,包括创建、调度、暂停和恢复。调度器采用协作式调度(cooperative scheduling),Goroutine在执行系统调用、I/O操作等可能导致阻塞的操作时,会主动让出CPU,让调度器有机会调度其他Goroutine。
  3. M的管理:runtime通过系统调用向操作系统获取M,并将M与Goroutine进行绑定和解绑。当一个M上的Goroutine阻塞时,runtime会创建新的M来运行其他可运行的Goroutine,以充分利用CPU资源。同时,当M上的所有Goroutine都执行完毕或阻塞时,runtime会将M归还给操作系统,避免资源浪费。