Go 并发编程面试题, Go 语言中 Goroutine 的调度时机有哪些?
Go 并发编程面试题, Go 语言中 Goroutine 的调度时机有哪些?
QA
Step 1
Q:: Go 语言中 Goroutine 的调度时机有哪些?
A:: Goroutine 的调度主要由 Go 语言的调度器(Scheduler)决定。调度时机可以包括:Goroutine 被创建时、Goroutine 被阻塞时(如 I/O 操作)、Goroutine 主动调用 runtime.Gosched()
让出 CPU 时间片时、Goroutine 的栈空间被耗尽且需要扩展时、Goroutine 执行完成时等。Go 的调度器基于 GMP 模型(Goroutines、Machine、Processor),通过工作窃取(Work Stealing)和其他策略来高效地调度和分配 Goroutine。
Step 2
Q:: 什么是 GMP 模型?
A:: GMP 模型是 Go 语言调度器的核心机制。G 代表 Goroutine,M 代表 Machine(实际的线程),P 代表 Processor(逻辑处理器)。Goroutine 通过 P 绑定到 M 上执行。P 的数量与设置的最大并行数有关,通常等于机器的 CPU 核心数。通过 GMP 模型,Go 可以实现高效的 Goroutine 调度,最大化资源利用率。
Step 3
Q:: Go 语言如何实现 Goroutine 的并发调度?
A:: Go 语言通过基于 GMP 模型的调度器实现 Goroutine 的并发调度。调度器会根据系统资源(如 CPU 核心数)、任务的特性(如 I/
O 密集型或计算密集型)、任务的优先级等因素来动态调度 Goroutine。Goroutine 的创建和销毁成本非常低,因此 Go 可以高效管理大量 Goroutine,同时避免了传统线程模型的上下文切换开销。
Step 4
Q:: Go 中 Goroutine 的栈是如何管理的?
A:: Goroutine 的栈大小在创建时非常小(约 2
KB),并且会根据需要动态增长和收缩。Go 使用了一种分段栈(Segmented Stack)机制,使得 Goroutine 在遇到栈溢出时可以自动扩展栈空间。当栈空间不再需要时,它也会自动收缩,以节省内存。
Step 5
Q:: 在 Go 中如何进行 Goroutine 间的通信?
A:: Go 中 Goroutine 间的通信主要通过 Channel 实现。Channel 是一种类型安全的管道,通过它可以在不同 Goroutine 之间发送和接收数据。Channel 本身是并发安全的,支持同步(阻塞)和异步(缓冲)通信模式。