golang调度的基本单元是协程,协程是比线程更加轻量的执行单元,它是由go runtime在用户态实现,它比线程依赖于系统调度显得更加轻量。
golang的调度实现经历很多次的更新迭代,不断的完善。截止go1.13版本,golang的调度实现已经兼备协作式调度和抢占式调度,但是这个抢占式调度是基于协作的抢占式调度。在go1.14版本后开始引入基于信号的抢占式调度。
抢占式调度
抢占式调度是指依靠外部抢占的方式去中断当前任务,让其放弃当前资源交给其他正在等待的任务,这显得比较被动和强迫。
优点:
- 任务执行时间可控。
- 不会出现不合理分配的情况,保证公平性。
缺点:
- 实现复杂
- 抢占操作会导致一些额外开销。
- 由于无法感知任务的执行情况,对于单个任务的执行效率无法做到最优。
- 调度程序需要保存任务的上下文。
提示:在go1.14版本后开始引入基于信号的抢占式调度,是一种异步抢占机制。
协作式调度
协作式调度是指以多个任务之间以协作的方式切换执行,每个任务执行一会,任务执行到某个点时会自己让出当前资源交给其他正在等待的任务,这显得比较主动和自愿。
优点:
- 实现简单。
- 任务可以自己控制放弃资源的时间。
- 由于任务保持自己的生命周期,调度程序不必注意每个任务的状态。
缺点:
- 执行时间不可控,如果遇到流氓任务一直不放弃资源会导致其他任务得不到资源被饿死。
- 新任务执行实时性差