Goroutine-工作线程的唤醒和创建详解

本文深入探讨Go语言中Goroutine的唤醒与创建过程,涉及如何将等待的Goroutine放入运行队列、何时创建新工作线程、以及线程的唤醒和创建细节。通过分析`ready`、`wakep`、`startm`和`newm`等函数,揭示Go运行时如何高效地管理线程,确保CPU资源充分利用。

原文地址:Goroutine-工作线程的唤醒和创建详解

本文需要关注如下两个问题:

  1. 如何唤醒睡眠中的工作线程?

  2. 如何创建新的工作线程?

上篇文章聊到ready通过将需唤醒的goroutine放入运行队列来唤醒它,本文接着分析。

为充分利用CPU,ready在唤醒goroutine之后会验证是否需要创建新的工作线程来工作,验证规则就是,如果当前有空闲的p而没有工作线程正在尝试从各个工作线程本地运行队列偷取goroutine(没有spinning状态的工作线程)的话,就需将空闲的p叫起来工作,来看runtime/proc.go文件639行代码分析ready:

// Mark gp ready to run.func ready(gp *g, traceskip int, next bool) {
  
      ......    // Mark runnable.    _g_ := getg()    ......    // status is Gwaiting or Gscanwaiting, make Grunnable and put on runq    casgstatus(gp, _Gwaiting, _Grunnable)    runqput(_g_.m.p.ptr(), gp, next) //放入运行队列    if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
  
          //有空闲的p而且没有正在偷取goroutine的工作线程,则需要唤醒p出来工作        wakep()    }    ......}

唤醒空闲p是由wakep完成,来看runtime/proc.go文件2051行代码:

// Tries to add one more P to execute G's.// Called when a G is made runnable (newproc, ready).func wakep() {
  
      // be conservative about spinning threads    if !atomic.Cas(&sched.nmspinning, 0, 1) {
  
          return    }    startm(nil, true)}

wakep先通过cas操作再次确认是否有其它工作线程处于spinning状态,之所以要使用cas操作再次确认,就是因为当前工作线程是通过【atomic.Load(&sched.npidle)!= 0 && atomic.Load(&sched.nmspinning) == 0】这个条件来判断启动工作线程之后到真正启动工作线程之前这段时间内是否有工作线程进入spinning状态,正在四处寻找需要运行的goroutine,有的话,就不需创建了。

如cas操作成功,则继续调用startm创建一个新的或是唤醒一个处于睡眠状态的工作线程出来工作。

来看runtime/proc.go文件1947行代码分析startm:

// Schedules some M to run the p (creates an M if necessary).// If p==nil, tries to get an idle P, if no idle P's does nothing.// May run with m.p==nil, so write barriers are not allowed.// If spinning is set, the caller has incremented nmspinning and startm will// either decrement nmspinning or set m.spinning in the newly started M.//go:nowritebarrierrecfunc startm(_p_ *p, spinning bool) {
  
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luyaran

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值