首页 > 其他分享 >goroutine

goroutine

时间:2022-10-04 16:26:02浏览次数:41  
标签:队列 创建 goroutine 调度 线程 运行

一、介绍

goroutine 是 Go语言中的轻量级线程,用户态级别,由 Go 运行时(runtime)调度和管理,它比线程更加易用、高效和轻便

每一个并发的执行单元叫作一个goroutine,Go 程序会自动为 main() 函数创建一个默认的goroutine

 

1 goroutine和线程的区别

1) 内存消耗
创建一个goroutine的栈内存消耗为 2 KB,如果栈空间不够用,会自动进行扩容
创建一个线程需要消耗 1 MB 栈内存,而且还需要一个被称为 "a guard page" 的区域用于和其他线程的栈空间进行隔离


2) 创建和销毀
线程创建需要向操作系统申请资源,销毀时将资源归还,因此创建和销毀线程的资源消耗比较大,属于内核级
goroutine的创建和销毁是由 Go runtime 负责管理的,消耗非常小,属于用户级

3) 切换
线程的调度方式是抢占式的,切换时需要保存各种寄存器,以便将来恢复。线程切换会消耗 1000-1500 ns
goroutine的调度方式是协同式的,切换时只需保存三个寄存器: Program Counter, Stack Pointer and BP。goroutine 切换会消耗 200 ns

 

 2 创建goroutine

使用 go 关键字创建一个goroutine,一个函数可以被创建多个goroutine,一个goroutine必定对应一个函数

每个groutine中的返回值都会被忽略,如果需要从goroutine中返回数据,请使用通道(channel)把数据从goroutine中返回

 

格式

go 函数名(参数列表)

 

二、Golang的GMP模型

1 GMP模型

G(Goroutine): go协程

M(Machine): 工作线程或内核线程,G 需要调度到 M 上才能运行

P(Processor): 调度器,负责调度goroutine,保存了当前goroutine运行的上下文(函数指针,堆栈地址及地址边界),同时还负责部分内存的管理。维护一个本地goroutine队列,M从P上获得goroutine并执行

 

其中:

M 与 P 的数量没有绝对关系

P在程序启动时创建,个数在程序启动时决定,由环境变量GOMAXPROCS的值或程序运行runtime.GOMAXPROCS()进行设置,默认情况下等同于CPU的核数

没有足够的M来关联P并运行其中的可运行的G时创建M

G需要在M上才能运行,M通过P的调度获取G,在某一时刻,一个M上只有一个G在运行(g0除外)

P拥有一个G队列,里面是已经就绪的G,是可以被调度到线程栈上执行的协程,称为运行队列

M堵塞,P会创建或者切换一个新的M

 

2 关系图

其中:

goroutine队列中: 黄色的G表示正在执行中的goroutine,灰色的G表示等待调度的goroutine

 

3 调度策略   1) 从工作线程M的本地运行队列中寻找goroutine 2) 从全局运行队列中寻找goroutine,并不是每次调度都会从全局队列获取可运行的 goroutine。每个工作线程每经过61次调度就需要优先尝试从全局运行队列中找出一个goroutine来运行,这样做的原因:保证调度的公平性,保证位于全局运行队列中的goroutine得到调度的机会; 全局运行队列是所有工作线程都可以访问的,从全局获取需要上锁,开销大 3) 从其它工作线程的运行队列中偷取goroutine。如果经过上述策略还没有找到需要运行的goroutine,则从其他工作线程的运行队列中偷取goroutine,在偷取之前会再次尝试从全局运行队列和当前线程的本地运行队列中查找需要运行的goroutine,并且检测一下其他所有的 P 是否都处于空闲状态,如果是,则说明其他 P没有寻找到goroutine,进入休眠状态 4) 经过上述过程还是找不到goroutine,则进入休眠状态,在进入休眠状态之前还是会到全局运行队列中寻找goroutine,如果没有正式进入休眠状态,等待被其他 M 唤醒

标签:队列,创建,goroutine,调度,线程,运行
From: https://www.cnblogs.com/gudanaimei/p/16620037.html

相关文章

  • 【Golang】go语言中如何控制goroutine的数量
    一、现状在Go语言中,goroutine的创建成本很低,调度效率高,Go语言在设计时就是按以数万个goroutine为规范进行设计的,数十万个并不意外,但是goroutine在内存占用方面确实具有有......
  • 什么时候用Goroutine?什么时候用Channel?
    GO语言中的操作系统线程和goroutine的关系一个操作系统线程对应用户态多个goroutinego程序可以同时使用多个操作系统线程goroutine和系统线程事多对多的关系,即m:nG......
  • Go基础编程:并发编程—goroutine
    1goroutine是什么goroutine是Go并行设计的核心。goroutine说到底其实就是协程,但是它比线程更小,十几个goroutine可能体现在底层就是五六个线程,Go语言内部帮你实现了这些goro......
  • golang goroutine协程泄露
      语言级别的并发支持是Go的一大优势,但这个优势也很容易被滥用。通常我们在开始Go并发学习时,常常听别人说,Go的并发非常简单,在调用函数前加上go关键词便可启动g......
  • goroutine泄漏检测神器---goleak
     goroutine泄漏检测神器---goleak在日常开发中,go出去的goroutine通常伴随着死循环,这些goroutine可能处于阻塞状态,一直运行,直到进程结束。对于线上服务来说,一直是在运行......
  • go 语言 goroutine通信
    示例demo52packagemainimport("fmt")funccalc(taskChanchanint,resChanchanint,exitChanchanbool){forv:=rangetaskChan{......