一文详解golang中的gmp模型

 更新时间:2023年11月15日 11:07:44   作者:wric  
这篇文章主要介绍了golang中的gmp模型的诞生、概念及调度讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

诞生

(我们为什么需要gmp模型)

我们知道,早期的操作系统操作系统是单进程的。后来引入了并发的思想,发展为多进程/多线程操作系统,操作系统可以通过时间片在多个进程之间切换。然而,在多个进程之间进行切换,是需要切换成本的。

在引入协程之前,我们需要回顾一下进程和线程的概念。
进程,是软件的执行副本,是分配资源的基础单位。每个进程有自己的进程控制块,代码,数据。
线程,是轻量级的线程,是调度和执行的基本单位。(这里单指内核态线程),每个线程有自己的寄存器和栈。

时间与空间

在传统的多线程并发模型中,轻量级的线程只需进行寄存器和栈等上下文的切换就可以完成多个任务的并发执行。然而,随着并发量越来越高,有些局限性开始展现出来。

随着并发量的上涨,切换的频率越来越高,线程的切换开销开始显露不足
随着并发量的上涨,需要越来越多的线程,内存占用也越来越大

因此,在高并发的需求下,协程因此诞生了,也就是golang中的groutine。

在时间上,平均每次协程切换的开销是 120ns 左右,相对于进程切换的开销大约 3.5us,大约是其的三十分之一
在空间上,协程初始化创建的时候为其分配的栈有 2KB,而线程栈一般在4-8M左右。

那么,为什么协程可以这么轻量呢。

在传统的多线程中,线程与进程的关系是固定的,每个线程必定从属于一个进程。而到了协程,为了去掉更多的枷锁,协程是不依赖于某个固定的线程的,协程可以自由切换而不比。换而言之,golang在用户空间与内核空间之间创建了一层新的映射,而这,就是gmp模型。

概念

(gmp是什么)

gmp=groutine+machine+processor

G

  • (1) g 即goroutine,是golang中对协程的抽象;
  • (2) g有自己的运行栈、状态、以及执行的任务函数(用户通过go func指定);
  • (3) g需要绑定到p才能执行,在g的视角中,p就是它的cpu.

M

  • (1) m 即machine,是golang 中对线程的抽象;
  • (2) m的数量是动态的,golang语言中默认最大值为10000,也可以用runtime/debug包中的SetMaxThreads函数来设置
  • (3) ⼀个M阻塞,会创建⼀个新的M。如果有M空闲,那么就会回收或者睡眠。

P

  • (1) p即 processor,是golang 中的调度器;
  • (2) p是 gmp的中枢,借由p承上启下,实现g 和m之间的动态有机结合;
  • (3)对g而言,p是其cpu,g只有被p调度,才得以执行;
  • (4)对m而言,p是其执行代理,为其提供必要信息的同时(可执行的g、内存分配情况等),并隐藏了繁杂的调度细节;
  • (5) p 的数量决定了g最大并行数量,可由用户通过GOMAXPROCS进行设定(超过CPu核数时无意义).也可以在程序中通过runtime.GOMAXPROCS() 来设置

gmp模型图片

调度

调度策略1 work steal
自己的本地队列为空时,会去别的本地队列偷取一半,保证有任务可以执行。

调度策略2 hand off
当一个绑定了M的G发生阻塞,会创建/唤醒

调度策略3 并行
最多有GOMAXPROCS个线程分布在多个CPU上同时运⾏

调度策略4 抢占
在Go中,⼀个goroutine最多占⽤CPU 10ms,防⽌其他goroutine被饿死

调度策略5 全局队列
当M执⾏work stealing从其他P偷不到G时,它可以从全局G队列获取G。

以上就是详解golang中的gmp模型的详细内容,更多关于详解golang中的gmp模型的资料请关注脚本之家其它相关文章!

相关文章

  • Go error的使用方式详解

    Go error的使用方式详解

    当我们需要在Go项目中设计error,就不得不先知道Go error几种常用方法,今天通过本文给大家介绍Go error的使用方式详解,感兴趣的朋友一起看看吧
    2022-05-05
  • golang常用库之pkg/errors包第三方错误处理包案例详解

    golang常用库之pkg/errors包第三方错误处理包案例详解

    这篇文章主要介绍了golang常用库之pkg/errors包第三方错误处理包,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • Golang使用etcd构建分布式锁的示例分享

    Golang使用etcd构建分布式锁的示例分享

    在本教程中,我们将学习如何使用Go和etcd构建分布式锁系统,分布式锁系统对于管理对分布式系统中共享资源的并发访问至关重要,它有助于维护一致性,防止竞争条件,并确保在任何给定时间只有一个进程独占访问资源,需要的朋友可以参考下
    2025-01-01
  • Go语言中的方法定义用法分析

    Go语言中的方法定义用法分析

    这篇文章主要介绍了Go语言中的方法定义用法,实例分析了方法的定义及使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • Golang报“import cycle not allowed”错误的2种解决方法

    Golang报“import cycle not allowed”错误的2种解决方法

    这篇文章主要给大家介绍了关于Golang报"import cycle not allowed"错误的2种解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以们下面随着小编来一起看看吧
    2018-08-08
  • 简单聊聊Go for range中容易踩的坑

    简单聊聊Go for range中容易踩的坑

    for循环问题,在面试中经常都会被问到,并且在实际业务项目中也经常用到for循环,要是没用好,一不下心就掉坑,本文就来讲讲Go for range中容易踩的坑吧
    2023-03-03
  • Go语言防范SQL注入CSRF及XSS攻击实例探究

    Go语言防范SQL注入CSRF及XSS攻击实例探究

    在本文中,我们将会介绍几种最常见的攻击类型,并且介绍如何使用Golang来防范这些攻击,本文会涉及XSS攻击、CSRF攻击、SQL注入等,如果你想学习Golang和网络安全的相关知识,那么这篇文章会是一个很好的开始
    2024-01-01
  • gin session中间件使用及源码流程分析

    gin session中间件使用及源码流程分析

    这篇文章主要为大家介绍了gin session中间件使用及源码分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • go自动下载所有的依赖包go module使用详解

    go自动下载所有的依赖包go module使用详解

    这篇文章主要介绍了go自动下载所有的依赖包go module使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Go 语言结构体链表的基本操作

    Go 语言结构体链表的基本操作

    链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,这篇文章主要介绍了Go 语言结构体链表,需要的朋友可以参考下
    2022-04-04

最新评论