320-go协程goroutine

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33781658/article/details/88691604





go协程goroutine







先说一下一些相关的关键性术语概念

1.并发
一个CPU上同时执行多个任务,CPU来回切换任务执行

2.并行
系统有多个CPU,每个CPU同一时刻都运行任务,互不抢占资源

3.进程
CPU在切换程序的时候,如果不保存上一个程序的状态,
直接切换下一个程序,就会丢失上一个程序的一系列状态,
所以引入了进程,用来划分运行时所需要的资源,
所以进程就是一个程序运行的时候所需要的基本资源单位,
也可以说是一个程序运行时的一个实体

4.线程
CPU切换多个进程的时候,会花费不少的时间,
因为切换进程,需要切换到内核态,
每次调度内核态,都需要读取用户态的数据,
进程一旦多起来,CPU调度会消耗很多资源,
所以引入了进程,进程本身几乎不占有资源,
这些线程共享进程里的资源,
内核调度起来不会像进程切换那么耗费资源

5.协程
协程拥有自己的寄存器上下文和栈,
协程调度切换的时候,将寄存器上下文和栈保存到其他地方,
在切回来的时候,恢复之前保存的寄存器上下文和栈,
所以协程能保存上一次调用时候的状态,
线程和进程的操作是由程序触发系统的接口,最后的执行者是系统,
协程的操作执行者是用户自身程序








调度模型

goroutine能够拥有强大的并发实现,
是通过GPM调度模型来实现的

Go的调度器内部有4个重要的结构
1.M
M代表内核级线程,一个M就是一个线程,
goroutine就是运行在M之上的,
M是一个很大的结构,里面维护小对象内存cache,当前执行的goroutine
以及随机数发生器等等非常多的信息

2.P
P-Processor,处理器,它的主要用途就是用来执行goroutine,
所以它也维护了一个goroutine队列,
里面存储了所有需要它来执行的goroutine

3.G
G代表一个goroutine,它有自己的栈,instruction pointer和其他信息,用于调度

4.Sched(scheduler)
代表调度器,维护有存储M和G的队列以及调度器的一些状态信息





GPM
G-goroutine
P-处理器
M-线程


每个M线程有一个P处理器,然后P处理器来处理G协程





协程
执行体是一个抽象的概念,在操作系统层面有多个概念与之对应
1.操作系统进程 process
2.进程内的线程 thread
3.进程内的协程 coroutine 

与传统的系统级别的进程和线程相比,协程最大的优势在于,轻量级
可以轻松创建上百万个而不会导致系统资源衰竭
而进程,线程通常 最多也不超过1万个

大多数的语言没有在语法层面直接支持协程
而是通过库的方式支持
但是用库的方式其实支持的功能也并不完整
比如仅仅提供了轻量级的线程的创建,销毁,切换的能力

go语言是在语言级别支持了轻量级的线程,goroutine
go语言标准库提供的所有系统调用操作(也包括所有同步IO操作)
都会出让CPU给其他goroutine
go协程的切换管理不依赖于系统的进程,线程
也不依赖CPU的核心数量







进程与线程的切换
进程维护着
1.进程地址空间
2.堆栈
3.寄存器

线程维护着
1.堆栈
2.寄存器

进程切换要 切换地址空间 还要 保存寄存器状态
线程切换要轻量得多,但是依然消耗较多资源




协程切换
进程和线程的执行者是系统
而协程的执行者是程序
所以系统不能操控协程
协程的切换完全由程序来控制
所以比系统要快



猜你喜欢

转载自blog.csdn.net/qq_33781658/article/details/88691604