欢迎访问 内存溢出 —— 独立后端与系统工程技术博客

专注于分布式系统、Linux内核、数据库存储与后端工程实践

Go 语言 GMP 调度器模型与协作式抢占机制

发表于:|最后更新:|分类:后端开发|阅读:6443 次

Go 语言能够轻松处理十万级高并发的核心支柱在于其轻量级协程(Goroutine)及其专属的 GMP 调度模型。G 代表 Goroutine,其初始栈空间仅为 2KB,可随执行栈深动态扩缩;M 代表 Machine,映射真实的系统操作线程;P 代表 Processor,承载调度逻辑所需的上下文与本地运行队列。GMP 架构有效解决了传统单个全局锁带来的多核竞争瓶颈。每个 P 维护一个容量为 256 的本地无锁队列,M 优先从关联 P 的本地队列获取就绪的 G 进行上下文执行。当本地队列清空时,调度器会触发 Work Stealing 机制,从其他 P 的队列尾部窃取一半的任务以实现负载均衡;若所有本地队列皆空,则进入全局队列查找。早期 Go 语言依赖函数调用插桩实现协作式调度,一旦遇到紧凑的 CPU 密集型循环(无函数调用),会导致 Goroutine 独占线程无法让出。Go 1.14 引入了基于 POSIX 信号机制的异步抢占(Non-cooperative Preemption)。sysmon 守护线程持续轮询,发现执行时间超过 10ms 的 G 时,向目标 M 发送 SIGURG 信号。目标线程捕获信号并中断当前流水线,在信号处理函数中注入调度指令,强制当前 G 保存寄存器让出 CPU,保证了调度的公平性。