文章目录
GoLang之GMP常见问题总结
1.gmp当一个g堵塞时,g、m、p会发生什么?
M 会阻塞,如果当前有 G 在执行,调度器会触发hand off机制,会将 MP 进行分离,如果有空闲的M就用或者是从线程池中取,如果都没有就创建一个新的M 来服务于这个 P,当M进行系统调用结束的时候,这个G会尝试获取一个空闲的 P 执行,并放入到这个 P 的本地队列。如果获取不到 P,那么这个线程 M 变成休眠状态, 加入到空闲线程中,然后这个 G 会被放入全局队列中。
总结:
即 M阻塞,MP会进行分离,寻找空闲的M;
系统调用结束后:G寻找空闲的P执行,加入P本地队列,如果获取不到,M休眠,G加入全局队列
造成阻塞还有一种情况:用户态阻塞(只是阻塞G)例如网络IO、阻塞式channel、sleep等场景(简单来说就是CPU这时候对于这个协程没有事情要做),对于这类阻塞会将G暂时挂起到某一临时等待队列中,待阻塞结束后重新寻找P放入。
2.Go协程阻塞太长时间会发生什么?
协程的切换时间片是10ms,也就是说 goroutine 最多执行10ms就会被 M 切换到下一个 G。这个过程,又被称为 中断,挂起;
3.Go协程阻塞太长时间会发生什么?
假设M的任务队列里有G1、G2,G1遇到异步系统调用时,M会先执行G2,G1异步返回时,插入回M的任务队列尾部。
4.Go协程遇到同步系统调用是怎么做的?
假设M的任务队列里有G1、G2,G1遇到同步系统调用时,G1会被调度到另外一个完全空闲的M上执行(如果不存在,则先创建一个新的M),G1同步返回时,插入回M的任务队列尾部。
5.工作窃取
当一个M的任务队列空闲时,可以从其他M或全局任务队列窃取任务。窃取优先级是:
1.其他M
2.全局