前言:

       golang的runtime提供了一个LockOSThread的函数,该方法的作用是可以让当前协程绑定并独立一个线程 M。 那么绑定线程的那个协程new出来的子协程在哪里跑?  先说答案,子协程不会继承lockOSThread特性。 是否是这样,我们可以试一下 … 


该文章后续仍在不断的更新修改中, 请移步到原文地址 http://xiaorui.cc/?p=5320

测试代码

注释, 通过 syscall.Gettid()是可以获取当前G绑定的线程id  (lwp).

测试代码的日志结果很明显,虽然我们在main主协程里配了runtime.LockOSThread()线程绑定,但因为net/http底层会针对每个accept后的连接new一个子协程,这些子协程不会继承父协程的LockOSThread线程绑定。

除了syscall方法外,我们还可以 include <pthread.h> 方法来打印线程标识,C.phread_self() 来输出线程标识。

为什么golang的子协程不能继承main goroutine的线程绑定?

 因为官方doc有runtime.LockOSThread线程方面的描述,包括子协程. https://tip.golang.org/doc/go1.10#runtime

golang nuts和issuse里有不少帖子是关于子协程线程绑定的,看样子作者是没有兴趣做这方面的扩展,主要会影响当前的go的调度策略。 有兴趣的朋友可以追看下issuse页 https://github.com/golang/go/issues/23758

什么场景下用到runtime.LockOSThread ?

我们知道golang的scheduler可以理解为公平协作调度和抢占的综合体,他不支持优先级调度。当你开了几十万个goroutine,并且大多数协程已经在runq等待调度了, 那么如果你有一个重要的周期性的协程需要优先执行该怎么办?

可以借助runtime.LockOSThread()方法来绑定线程,绑定线程M后的好处在于,他可以由system kernel内核来调度,因为他本质是线程了。  

先前我们有在定时器场景中使用runtime.LockOSThread,达到少许的优先级效果。效果不明显的原因是,我们自定义的定时器需要time.sleep来解决cpu忙讯轮,但time.sleep又依赖于go自身的heap定时器…. 解决方法是,独立一个M线程后,使用syscall来实现时间等待. 

总结:

runtime.LockOSThread会锁定当前协程只跑在一个系统线程上,这个线程里也只跑该协程。他们是相互牵制的 !!! 

END.



对Python及运维开发感兴趣的朋友可以加QQ群 : 478476595 !!!
{ 2000人qq大群内有各厂大牛,常组织线上分享及沙龙,对高性能及分布式场景感兴趣同学欢迎加入该QQ群 }

另外如果大家觉得文章对你有些作用!   帮忙点击广告. 一来能刺激我写博客的欲望,二来好维护云主机的费用.
如果想赏钱,可以用微信扫描下面的二维码. 另外再次标注博客原地址  xiaorui.cc  ……   感谢!
暂无相关产品

评论已关闭。