golang LockOSThread子协程绑定问题

rfyiamcool · · 2372 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前言:

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


测试代码

注释, 通过 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会锁定当前协程只跑在一个系统线程上,这个线程里也只跑该协程。他们是相互牵制的 !!! 


有疑问加站长微信联系(非本文作者)

本文来自:峰云就她了

感谢作者:rfyiamcool

查看原文:golang LockOSThread子协程绑定问题

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2372 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传