调度器对并发任务的基本管理
- 任务创建:在Go语言中,通过
go
关键字创建并发任务(goroutine)。例如go func() { /* 任务逻辑 */ }()
,这会将一个函数调用封装成一个独立的执行单元,即goroutine,交给Go调度器管理。
- 排队:Go调度器使用M:N调度模型。它有多个
M
(操作系统线程)和多个N
(goroutine)。调度器维护多个本地队列(每个M
有一个本地队列)和一个全局队列。当创建一个goroutine时,它优先被放入当前M
对应的本地队列。如果本地队列已满,则放入全局队列。
- 执行顺序:调度器采用协作式调度。
M
从本地队列获取goroutine来执行。如果本地队列为空,M
会尝试从全局队列获取任务,或者从其他M
的本地队列偷取任务(work - stealing机制)。在执行过程中,当一个goroutine执行了像I/O操作、系统调用、time.Sleep
、channel操作等可能导致阻塞的操作时,它会主动让出M
,调度器会安排其他可运行的goroutine在这个M
上执行。
示例代码
package main
import (
"fmt"
)
func task1() {
fmt.Println("Task 1 is running")
}
func task2() {
fmt.Println("Task 2 is running")
}
func main() {
go task1()
go task2()
// 防止主线程退出,以便goroutine有机会执行
select {}
}