MST
星途 面试题库

面试题:Go中Goroutine并发模型的特点及与线程池的简单对比

请阐述Go语言中Goroutine并发模型的主要特点,包括其轻量级特性体现在哪些方面。并简要说明Goroutine与传统线程池在资源开销、调度方式上的区别。
26.5万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

Goroutine并发模型主要特点

  1. 轻量级:Goroutine的创建和销毁开销极小。相比传统线程,创建一个线程需要分配较大的栈空间(通常数MB),而Goroutine初始栈空间只需2KB左右,并且栈空间可以根据需要动态增长和收缩。这使得在同一程序中可以轻松创建数以万计的Goroutine,而创建同样数量的传统线程会耗尽系统资源。
  2. 基于消息传递的通信:通过channel进行数据传递和同步,遵循“不要通过共享内存来通信,而要通过通信来共享内存”的原则。这种方式使得并发编程更加安全和易于理解,避免了传统共享内存并发编程中常见的竞态条件等问题。
  3. 自动调度:Go语言运行时系统(runtime)有自己的调度器,负责Goroutine的调度。它采用M:N调度模型,即多个Goroutine映射到多个操作系统线程上。运行时调度器会在操作系统线程上多路复用Goroutine,在合适的时机进行切换,不需要程序员手动管理线程上下文切换等复杂操作。

Goroutine轻量级特性体现

  1. 栈空间小:初始栈空间仅2KB,远小于传统线程栈空间。
  2. 创建开销低:创建Goroutine时,只需分配少量内存用于结构体和初始栈,而创建线程需要操作系统内核参与,涉及较多系统调用和资源分配。
  3. 销毁开销低:Goroutine结束时,运行时系统可以快速回收其占用的资源,而线程销毁可能涉及复杂的内核操作。

Goroutine与传统线程池区别

  1. 资源开销
    • Goroutine:资源开销极小,创建、销毁和运行时占用资源少,可大量创建。能在有限资源下支持高并发场景。
    • 传统线程池:线程创建开销大,每个线程占用较多内存(栈空间大),线程池大小受系统资源限制,不能无限制创建线程。
  2. 调度方式
    • Goroutine:由Go运行时调度器管理,采用M:N调度模型,在用户态进行调度,不依赖操作系统内核调度,上下文切换开销小。调度器基于协作式调度,Goroutine在执行系统调用、I/O操作或主动调用runtime.Gosched()时,才会让出执行权。
    • 传统线程池:线程由操作系统内核调度,采用1:1调度模型,即一个线程对应一个内核线程。上下文切换需要陷入内核态,开销较大。内核基于抢占式调度,根据线程优先级等因素强制切换线程执行权。