Go Runtime(十):Timer实现
本文源码基线为 Go 1.26.2、Linux/amd64。Go 1.23 重写了 Timer Channel 的可回收性与 Stop/Reset 保证;阅读旧版本分析时必须先确认版本边界。 Timer 不是一个独立后台 goroutine 加一张全局表。Go 1.26 把真实时间 Timer 组织在每个 P 的四叉最小堆中,由调度器和 netpoll 共同决定睡到何时、何时执行到期回调。 它同时服务 time.Sleep、time.Timer、time.Ticker、AfterFunc 和网络 Deadline。难点不只是“按时间排序”,而是并发 Stop/Reset、跨 P 修改、周期跳期、Channel 旧值以及 GC 可达性。 time包如何进入runtime time 包通过 runtime 提供的私有入口创建和修改 Timer: TEXTtime.Sleep -> runtime.timeSleep time.NewTimer -> runtime.newTimer(sendTime, channel) Timer.Stop -> runtime.stopTimer Timer.Reset -> runtime.resetTimer time.AfterFunc -> runtime.newTimer(goFunc, nil) net deadline -> runtime timer callback time.NewTimer 的源码仍写 make(chan Time, 1)。默认模式下 runtime 借助 hchan.timer 对外呈现同步、容量为零的语义;设置 GODEBUG=asynctimerchan=1 才恢复 Go 1.23 以前的异步 Timer Channel 行为。因此不能只看 make 参数推断 cap(t.C) 和 Stop/Reset 语义。 ...