sysmon 触发的抢占调度

lana · · 3967 次点击 · 开始浏览    置顶
这是一个创建于 的主题,其中的信息可能已经有所发展或是发生改变。

// 情景1 package main import ( "fmt" ) var sum1, summain int64 func add1() { for i := 0; i < 1000; i++ { for j := 0; j < 10000; j++ { sum1++ } } } func main() { go add1() for i := 0; i < 10000; i++ { for j := 0; j < 10000; j++ { summain++ } } fmt.Println(sum1, sum1) } // 结果:10000000 100000000 // 解释: 1:由于main函数中的for 循环执行时间比较长,所以sysmon监控线程会对当前routine设置抢占标记 2:disassemble main.main 反汇编main函数发现,fmt.println() 调用的函数是runtime.convT2E(t *_type, elem unsafe.Pointer) 这里压入栈的数据是sum1的指针,但是这时函数首先调用morestack调度到另一个goroutine了,因此第一个结果为10000000 // 情景2 package main var sum1, summain int64 func add1() { for i := 0; i < 1000; i++ { for j := 0; j < 10000; j++ { sum1++ } } } func main() { go add1() for i := 0; i < 10000; i++ { for j := 0; j < 10000; j++ { summain++ } } println(sum1, sum1) } // 结果:0 100000000 解释: 1:同上 2: 反汇编之后发现println汇编实际调用的是runtime.printint 因此参数入栈的是sum1的初始值0,而后goroutine调度sum1虽然增加,但是printint的值是已经入栈的参数值所以第一个结果为0 当然如果这里把sysmon 停掉 //onM(newsysmon),结果就都是 0 0

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

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

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