为什么?因为设计线程模型M:N,协程大杀器,无论在单个占用内存,还是切换成本,还是GMP的设计,从Go诞生开始,就是为高并发而生。
协程
协程,是一种比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是由程序所控制(也就是在用户态执行)。这样带来的好处就是性能得到了很大的提升,不会像线程切换那样消耗资源。
背景
Process(进程) -> Thread(LWP,lightweight process轻量级进程)——CPU调度的最小单位 -> Goroutine(lightweight userspace thread轻量级用户空间线程)——用户态
从进程到协程,就是不断共享,减少切换成本的过程。到了协程已经完全是由程序所控制,在用户态执行,不像线程切换一样耗费资源。多个协程在一个线程中执行。
协程结构体和切换函数
一个协程代表一个执行流,执行流包含有需要执行的函数、函数的入参、当前执行流的状态和进度(对应CPU的PC寄存器和SP寄存器),还有保存状态的地方,用于执行流恢复。(因为不涉及线程栈,所以栈空间很小默认2kb)
有了执行流的形式后,用户系统基本就可以模拟CPU切换的过程。问题是待运行的协程呢?在哪排队呢?
GM模型
在Go1.0的时候,调度队列schedt是全局的,要共同竞争一把锁。每个CPU绑定一个Mÿ