其他分享
首页 > 其他分享> > 【Golang详解】调度机制 抢占式调度

【Golang详解】调度机制 抢占式调度

作者:互联网

Golang抢占式调度

在1.2版本之前,go的调度器仍然不支持抢占式调度,程序只能依靠Goroutine主动让出CPU资源才能触发调度,这会引发一些问题,比如:

之后go team意识到这个问题,首先推出了基于协作的抢占式调度



基于协作的抢占式调度

Go团队为 Goroutine 引入 stackguard0 字段,当该字段被设置成 StackPreempt 意味着当前 Goroutine 发出了抢占请求;同时在 runtime.newstack:1e112cd 中增加抢占的代码,当 stackguard0 等于 StackPreempt 时触发调度器抢占让出线程;

1.13版本 go依赖调用函数栈增长检测代码的方式

gorogoutine创建之初,栈的大小是固定的,为了防止栈溢出,编译器会在有明显栈消耗的函数头部插入一些检测代码,通过stackguard0值来决定是否触发runtime.morestack函数。将stackguard0设置为StackPreempt 作用是进入函数时必定触发runtime.morestack,然后在调用runtime.newstack

所以基于协作的抢占式调度的工作机制就是:

但是这种调度并不完备,比如一个goroutine运行了很久,但是它并没有调用另一个函数,则它不会被抢占。例如

请添加图片描述

这段代码在这种调度方式下会阻塞,是因为空的for循环没有调用函数

在Go的1.14版本中实现了非协作的抢占式调度



基于信号的抢占式调度

在之前的依赖栈增长检测代码的方式,遇到没有函数调用的情况下就会出现问题,在Go1.14这一问题得到解决。

在Linux中这种真正的抢占式调度是基于信号完成的,所以也称为“异步抢占”

“异步抢占”工作机制:

标签:goroutine,抢占,Goroutine,式调度,Golang,详解,线程,runtime
来源: https://www.cnblogs.com/CJ-cooper/p/15265189.html