MST

星途 面试题库

面试题:Go中Goroutine与线程调度策略的主要差异

请阐述Go语言中Goroutine与传统线程在调度策略方面的主要差异,包括调度器的工作方式、资源占用等方面。
33.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

调度器工作方式差异

  1. Goroutine调度器
    • M:N调度模型:Go语言使用M:N调度模型,即多个Goroutine(N个)可以映射到多个操作系统线程(M个)上。Go的调度器在用户态实现,被称为G-M-P模型。其中G代表Goroutine,M代表操作系统线程,P代表处理器(Processor)。P的数量一般等于CPU核心数,它提供了执行Goroutine的资源,M必须关联到一个P才能执行Goroutine。
    • 协作式调度:Goroutine采用协作式调度(co - operative scheduling),也叫非抢占式调度。当一个Goroutine执行系统调用(如I/O操作)或主动调用runtime.Gosched()时,它会主动让出CPU,调度器会安排其他可运行的Goroutine在该M上执行。
  2. 传统线程调度器
    • 1:1调度模型:传统线程通常采用1:1调度模型,即一个线程对应一个操作系统线程。操作系统内核负责线程的调度,这是基于抢占式调度(pre - emptive scheduling)。
    • 抢占式调度:操作系统内核会根据线程的优先级、时间片等因素,在合适的时机强制暂停当前运行的线程,并切换到其他线程执行。例如,当一个线程的时间片用完,内核会中断该线程,将CPU资源分配给其他线程。

资源占用差异

  1. Goroutine
    • 轻量级:Goroutine非常轻量级,创建和销毁的开销很小。一个Goroutine初始栈大小通常只有2KB,并且栈空间可以根据需要动态增长和收缩。由于多个Goroutine可以复用少量的操作系统线程,所以在创建大量并发任务时,内存占用和资源开销相对较低。
  2. 传统线程
    • 重量级:传统线程相对较重,创建和销毁的开销较大。每个线程都需要占用一定的内核资源,包括内核栈(通常为几MB),并且线程上下文切换的开销也比较大。因此,在创建大量线程时,会消耗较多的系统资源,容易导致系统性能下降。