Golang协程调度
版权声明 本站原创文章 由 萌叔 发表 转载请注明 萌叔 | http://vearne.cc 本文基于go1.17.6 1.什么是协程? 协程,英文Coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序员自己写程序来管理的轻量级线程叫做『用户空间线程』, 具有对内核来说不可见的特性。 1.1 协程的特点 线程的切换由操作系统负责调度,协程由用户自己进行调度 线程的默认Stack大小是MB级别,而协程更轻量,接近KB级别。 在同一个线程上的多个协程,访问某些资源可以不需要锁 适用于被阻塞的,且需要大量并发的场景。 1.2 Golang的GMP模型 CPU驱动线程上的任务执行 线程由操作系统内核进行调度,Goroutine由Golang运行时(runtime)进行调度 P的 local runnable queue是无锁的,global runnable queue是有锁的 P的 local runnable queue长度限制为256 注意: M和P是绑定关系 M和G是绑定关系 P只是暂存G,他们之间不是绑定关系 E-R图 简化后的E-R图 注意: 后面为了书写简单直接将 local runnable queue表示为本地队列 global runnable queue表示为全局队列 延伸 timer的四叉堆和内存分配器使用的mcache也是每个P一个 Q: 为什么默认情况下P的数量与CPU数量一致? A: 这样可以避免把CPU时间浪费在上线文切换上 1.3 协程和线程的资源消耗对比 类别 栈内存 上下文切换 备注 Thread 1MB 1us 内存占用使用的是Java线程的默认栈大小 Goroutine 4KB 0.2us 内存占用使用的是Linux+x86下的栈大小 2. 常见的Goroutine 让出/调度/抢占场景 ...