移动局域网ip做网站,怎么做网站把图片发到网上,免费给人做网站的,岳阳水灾最新消息优秀文章
什么是GMP调度模型
Golang的一大特色就是Goroutine。Goroutine是Golang支持高并发的重要保障。Golang可以创建成千上万个Goroutine来处理任务#xff0c;将这些Goroutine分配、负载、调度到处理器上采用的是G-M-P模型。
什么是Goroutine
Goroutine Golang Coro…优秀文章
什么是GMP调度模型
Golang的一大特色就是Goroutine。Goroutine是Golang支持高并发的重要保障。Golang可以创建成千上万个Goroutine来处理任务将这些Goroutine分配、负载、调度到处理器上采用的是G-M-P模型。
什么是Goroutine
Goroutine Golang Coroutine。Goroutine是golang实现的协程是用户级线程。
Goroutine具有以下特点
相比线程其启动的代价很小以很小栈空间启动2Kb左右能够动态地伸缩栈的大小最大可以支持到Gb级别工作在用户态切换成本很小与内核线程关系是n:m即可以在n个系统线程上多工调度m个Goroutine
进程、线程、Goroutine
在仅支持进程的操作系统中进程是拥有资源和独立调度的基本单位。在引入线程的操作系统中线程是独立调度的基本单位进程是资源拥有的基本单位。在同一进程中线程的切换不会引起进程切换。在不同进程中的行线程切换会引起进程切换
两级线程模型 两级线程模型中用户线程与内核线程是多对多关系N : M。两级线程模型充分吸收上面两种模型的优点尽量规避缺点。其线程创建在用户空间中完成线程的调度和同步也在应用程序中进行。一个应用程序中的多个用户级线程被绑定到一些小于或等于用户级线程的数目内核级线程上。
Golang的线程模型
Golang在底层实现了混合型线程模型。M即系统线程由系统调用产生一个M关联一个KSE内核调度实体即两级线程模型中的系统线程。G为Groutine即两级线程模型的的应用级线程。M与G的关系是N:M。
GMP调度模型 G-M-P含义
G - GoroutineGo协程是参与调度与执行的最小单位M - Machine指的是内核级线程用过系统调用产生P - Processor指的是逻辑处理器P关联了的本地可运行G的队列(也称为LRQ)最多可存放256个G。
GMP调度流程
线程M想运行任务就需得获取 P即与P关联然从 P 的本地队列(LRQ)获取 G若LRQ中没有可运行的GM 会尝试从全局队列(GRQ)拿一批G放到P的本地队列若全局队列也未找到可运行的G时候M会随机从其他 P 的本地队列偷一半放到自己 P 的本地队列。拿到可运行的G之后M 运行 GG 执行之后M 会从 P 获取下一个 G不断重复下去。
G-M-P的数量
G 的数量 理论上没有数量上限限制的。查看当前G的数量可以使用runtime. NumGoroutine()
P 的数量 由启动时环境变量 $GOMAXPROCS 或者是由runtime.GOMAXPROCS() 决定。这意味着在程序执行的任意时刻都只有 $GOMAXPROCS 个 goroutine 在同时运行。
M 的数量: go 语言本身的限制go 程序启动时会设置 M 的最大数量默认 10000. 但是内核很难支持这么多的线程数所以这个限制可以忽略。 runtime/debug 中的 SetMaxThreads 函数设置 M 的最大数量 一个 M 阻塞了会创建新的 M。M 与 P 的数量没有绝对关系一个 M 阻塞P 就会去创建或者切换另一个 M所以即使 P 的默认数量是 1也有可能会创建很多个 M 出来。
调度的流程状态 从上图我们可以看出来
每个P有个局部队列局部队列保存待执行的goroutine(流程2)当M绑定的P的的局部队列已经满了之后就会把goroutine放到全局队列(流程2-1)
每个P和一个M绑定M是真正的执行P中goroutine的实体(流程3)M从绑定的P中的局部队列获取G来执行
当M绑定的P的局部队列为空时M会从全局队列获取到本地队列来执行G(流程3.1)当从全局队列中没有获取到可执行的G时候M会从其他P的局部队列中偷取G来执行(流程3.2)这种从其他P偷的方式称为work stealing
当G因系统调用(syscall)阻塞时会阻塞M此时P会和M解绑即hand off并寻找新的idle的M若没有idle的M就会新建一个M(流程5.1)。
当G因channel或者network I/O阻塞时不会阻塞MM会寻找其他runnable的G当阻塞的G恢复后会重新进入runnable进入P队列等待执行(流程5.3)
总结 Golang的线程模型采用的是混合型线程模型内核线程与协程用户线程关系是N:M。 Golang混合型线程模型实现采用GMP模型进行调度G是goroutine是golang实现的协程M是OS线程P是逻辑处理器。 每一个M都需要与一个P绑定P拥有本地可运行G队列M是执行G的单元M获取可运行G流程是先从P的本地队列获取若未获取到则从全局队列去获取如果仍然没有获取到则从其他P偷取过来即work stealing)若都未获取到则M将处于自旋状态并不会销毁。 当执行G时候发生通道阻塞等用户级别阻塞时候此时M不会阻塞M会继续寻找其他可运行的G当阻塞的G恢复之后重新进入P的队列等待执行若G进行系统调用时候会阻塞M此时P会和M解绑(即hand off)并寻找新的空闲的M。若没有空闲的就会创建一个新的M。
GMP高效的保证策略有 M是可以复用的不需要反复创建与销毁当没有可执行的Goroutine时候就处于自旋状态等待唤醒 Work Stealing和Hand Off策略保证了M的高效利用 M从关联的P中获取G不需要使用锁是lock free的