调度前世今生

  1. 单进程执行,不存在调度,一起都是先来后到顺序执行;

    1. 效率低下

    2. 阻塞

  2. 多进程/多线程调度,提高cpu利用率;

    1. 效率一般,上下文切换开销

    2. 阻塞

  3. 协程提高cpu利用率,协程比线程更加轻量,占用更少的资源,进程/线程占用虚拟内存4MB,线程大概几KB。

GPM调度算法

GPM调度算法的基本原则如下:

  1. 时间片轮转:每个任务被分配一个固定的时间片(时间量),当时间片用完后,系统将切换到下一个任务。这种方式确保了任务之间的公平性,每个任务都有机会执行。

  2. 优先级调度:每个任务可以分配一个优先级,优先级较高的任务会被优先执行。如果多个任务具有相同的优先级,可以采用时间片轮转的方式来调度它们。

  3. 阻塞和唤醒:当一个任务需要等待某个事件发生时,它会被阻塞(暂停执行),直到事件发生后被唤醒(恢复执行)。这种方式可以确保系统资源的有效利用,避免任务空转。

  4. 调度策略:GPM调度算法通常采用先来先服务(FCFS)或轮转调度策略。先来先服务策略按照任务到达的顺序执行,轮转调度策略按照时间片轮转的方式执行。

GPM模型

  1. G:表示执行的Goroutine

  2. P:表示逻辑处理器Process,所有的P程序启动时创建,并保持到数组中,最多有GOMAXPROCS个。P的本地队列和全局队列一样,存放的是待运行的G,存放数量有限,大概不超过256个,G所创建的G’优先放入P的本地队列中,避免切换带来的开销。

  3. M:表示线程,线程想运行任务就得获取P,从P的本地队列获取G,当P队列为空时,M也回尝试从全局队列获取一批放到P的本地队列,或者从其他P的本地队列重"偷"一半放到自己P的本地队列。

调度策略

  1. 复用线程,避免频繁创建、销毁线程。

    偷取机制当本地队列无运行的G,会从其他P去偷取一部分G放入本地队列。偷取的动作一定是由P发起的,而非M,因为P的数量是固定的,如果一个M得不到一个P,那么这个M是没有执行的本地队列的,更谈不上向其他队列P偷取。

    移交机制当本线程因为G进行系统调用阻塞时,线程会释放绑定的P,把P转移给其他空闲的线程执行。

  2. 利用并行

  3. 抢占

  4. 全局G队列