这是我参与「第五届青训营」伴学笔记创作活动的第3天
什么是协程
一个进程可以有多个线程,一个线程也可以有多个协程,协程的切换和创建完全由用户决定。
过程和协程的比较。
线程和进程完全由os分配,对于os来说,线程是最小的执行单元,进程是最小的资源管理单元。
和goroutine和线程的关系不同。 是针对线程的
goroutine
1.Goroutine通常需要2kb的内存,1mb的线程。
2.线程创建时需要向操作系统申请资源,并在丢弃时返回,因此其创建和丢弃的开销很大。相比之下,创建和丢弃goroutine的成本更低,因为go语言在运行时自己管理。
3.在开销更小的线程之间切换的调度方案是预置的,当一个线程的执行时间超过分配给它的时间片时,由其它可执行线程进行预置被说明。goroutine的调度是协调的,不与操作系统内核直接交流。
为什么要用协程
频繁地切换进程和线程是非常昂贵的。
过程转换的开销:
1、切换页表全局目录
2、内核状态栈的切换
3、切换硬件上下文。
4、刷新TLB
5 .系统调度器的代码运行
这些操作会产生以下弊端。
1.寄存器的内容丢失。
2.CPU cache失效,缓存命中失败。速度大幅下降。
3.TLB快速表失效,虚拟地址到物理地址的转换速度大幅降低
Goroutine实现原理
GMP模型 G (Goroutine):为每个Go关键字创建一个Go协程。 M (Machine):工作线程,在围棋中称为Machine。 P(处理器):在go中管理协程的数据结构 M必须有P才能执行G中的代码。P包含一个包含多个G的队列,P可以安排G由M执行。
总结
一般来说,GOMAXPROCS大小在程序运行时被设置为CPU核数,允许Go程序充分利用CPU。在一些IO密集型应用程序中,这个值可能并不意味着最佳性能。理论上,当Goroutine进入系统调用时,将启用或创建一个新的M,继续填充CPU。但是,由于Go调度器检测到M被阻塞,存在一定的延迟,即旧M被阻塞和新M运行之间存在一定的间隔,因此在IO密集型应用中,最好将GOMAXPROCS设置为较大的大小,这样可能会有较好的效果。