当golang调用 time.Sleep()时 调度器发生了什么 G、P和M之间又是怎样的关系?

其实这个问题就是想了解
golang中time.Sleep是如何实现的
在这背后调度器对time.Sleep又是如何处理的?

阅读 4.9k
2 个回答

又查阅了相关资料
自己总结一下

golang优化了time.Sleep()方法,避免其进行系统调用从而带来一些系统级别的开销
当我们在goroutine中调用time.Sleep()方法时
底层会创建一个 timer, 并将当前goroutine与timer进行绑定,并提供一个唤醒该goroutine的方法goroutineReady
然后通过addtimerLocked方法启动全局时间事件驱动器timerproc 并将timer加入到全局timer管理器中(timer 通过最小堆的数据结构存放每个定时器),且每一个加入到timer管理器中的timer都会被按唤醒时间进行排序,最早需要唤醒的timer排在最前面
再通过gopark()方法将当前goroutine状态标记为为_Gwaiting
解除G与M的绑定关系
调用schedule()函数,重新选择一个goroutine去执行

如何被唤醒呢?
timer管理器会寻找timer定时管理器的第一个timer并判断唤醒条件,满足条件后通过调用goroutineReady方法进行唤醒,主要操作是将对应的goroutine标记为_Grunnable并将其添加到P队列中等待被M执行

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题