runtime/time.go的addtimerLocked
// Add a timer to the heap and start or kick timerproc if the new timer is// earlier than any of the others.// Timers are locked.// Returns whether all is well: false if the data structure is corrupt// due to user-level races.func (tb *timersBucket) addtimerLocked(t *timer) bool { // when must never be negative; otherwise timerproc will overflow // during its delta calculation and never expire other runtime timers. if t.when < 0 { t.when = 1<<63 - 1 } t.i = len(tb.t) tb.t = Append(tb.t, t) if !siftupTimer(tb.t, t.i) { return false } if t.i == 0 { // siftup moved to top: new earliest deadline. if tb.sleeping && tb.sleepUntil > t.when { tb.sleeping = false notewakeup(&tb.waitnote) } if tb.rescheduling { tb.rescheduling = false goready(tb.gp, 0) } if !tb.created { tb.created = true go timerproc(tb) } } return true}runtime/time.go的timerproc
func timerproc(tb *timersBucket) { tb.gp = getg() for { lock(&tb.lock) tb.sleeping = false now := nanotime() delta := int64(-1) for { if len(tb.t) == 0 { //无timer的情况 delta = -1 break } t := tb.t[0] //拿到堆顶的timer delta = t.when - now if delta > 0 { // 所有timer的时间都没有到期 break } if t.period > 0 { // t[0] 是ticker类型 , 调整其到期时间并调整timer堆结构 // leave in heap but adjust next time to fire t.when += t.period * (1 + -delta/t.period) siftdownTimer(tb.t, 0) } else { //Timer类型的定时器是单次的 , 所以这里需要将其从堆里面删除 // remove from heap last := len(tb.t) - 1 if last > 0 { tb.t[0] = tb.t[last] tb.t[0].i = 0 } tb.t[last] = nil tb.t = tb.t[:last] if last > 0 { siftdownTimer(tb.t, 0) } t.i = -1 // mark as removed } f := t.f arg := t.arg seq := t.seq unlock(&tb.lock) if raceenabled { raceacquire(unsafe.Pointer(t)) } f(arg, seq) //sendTimer被调用的位置 --------------------------------------- lock(&tb.lock) } if delta < 0 || faketime > 0 { // No timers left - put goroutine to sleep. tb.rescheduling = true goparkunlock(&tb.lock, "timer goroutine (idle)", traceEvGoBlock, 1) continue } // At least one timer pending. Sleep until then. tb.sleeping = true tb.sleepUntil = now + delta noteclear(&tb.waitnote) unlock(&tb.lock) notetsleepg(&tb.waitnote, delta) }}
推荐阅读
- 盘点使用golang作为后台的科技公司
- 彻底搞懂虚拟地址翻译为物理地址的过程
- 一文看懂USB4
- 彻底搞懂虚拟内存,虚拟地址,虚拟地址空间
- 如何彻底搞懂Mysql事务原理
- MySQL高级进阶:关于InnoDB存储结构,一文深入分析讲解
- 帮你彻底搞懂 JS 中的 prototype、__proto__与constructor
- 一文看懂技术中台、研发中台、移动中台建设全攻略
- 一文弄清Python网络爬虫解析库!内含多个实例讲解
- 一文看完CDN的发展历程
