Go语言最广为人知的特性,应该就是goroutine了吧。我们都知道它能够并发地执行给定的操作,且能够稳定运行大量的goroutine,比线程进程性能强太多了,管理也很方便。挺好奇Go是怎样做到的,接下来就来瞧瞧。
在GMP之前,Go的调度模型是GM,它们分别是:
存在的问题:
先来个图总览一下:
从Go1.2开始,调度模型引入了P。它的处理器(Process)的抽象,但其实不是真正的CPU,能够分配到CPU资源的还是M。
P是怎样处理上面的问题的呢?
引入更多的管理策略,优化调度器性能
P如果运行完队列中的G,则能够盗取其它P的G或从全局队列中获取G
调度器会保证至少有一个M在自旋检查P和G有没有可绑定的,避免任务等待,但自旋也会浪费一些CPU算力。
sysmon会检查长时间运行的G,将其中断并重新放入调度。中断的原理是sysmon通过信号量通知G的M,往G的PC中插入特定指令,G执行该指令后将自己推入全局队列重新调度。
当G在执行阻塞调用时,M也会跟着阻塞并解绑P,但此时的P处于(syscall)不能调度给别的M。
因为runtime.GOMAXPROCS只是限制了P的数量(M的数量上限比较大),如果存在大量耗时长的系统调用,会导致创建大量的M并阻塞着,可能会导致系统资源耗尽。
Scalable Go Scheduler Design Doc
Linux下调用pthread库创建的线程是属于用户级线程还是内核级线程?
感谢您的阅读!
如果看完后有任何疑问,欢迎拍砖。
欢迎转载,转载请注明出处:http://www.yangrunwei.com/a/126.html
邮箱:glowrypauky@gmail.com
QQ: 892413924