定时器作为开发经常使用的一种数据类型,是每个开发者需要掌握的,对于一个高级开发很有必要了解它的实现原理,今天我们runtime源码来学习一下它的底层实现。
定时器分两种,分别为 Timer 和 Ticker,两者差不多,这里重点以Timer为例。
源文件位于 src/time/sleep.go
和 src/time/tick.go
。 go version 1.16.2
数据结构
Timer
数据结构
// src/runtime/sleep.go // The Timer type represents a single event. // When the Timer expires, the current time will be sent on C, // unless the Timer was created by AfterFunc. // A Timer must be created with NewTimer or AfterFunc. type Timer struct { C <-chan Time r runtimeTimer }
Timer 数据类型是表示单个事件。当计时器过期时,当前的时候将会发送到 Timer.C 通道,如果用 AfterFunc 创建计时器的话,则例外。
对于计时器必须由 NewTimer()
或 AfterFunc()
创建。
// Interface to timers implemented in package runtime. // Must be in sync with ../runtime/time.go:/^type timer type runtimeTimer struct { pp uintptr when int64 period int64 f func(interface{}, uintptr) // NOTE: must not be closure arg interface{} seq uintptr nextwhen int64 status uint32 }
字段说明
PP
当前对应的处理器P的指针when
定时器被唤醒的时间period
唤醒间隔时间,定时器为Timer数据类型时,此字段值为 0 时,否则为Ticker
数据类型f
唤醒后执行的函数,不能为闭包匿名函数
arg
唤醒后执行的函数的参数seq
?nextwhen
当定时器状态为timerModifiedEarlier
或timerModifiedLater
时,需要使用此字段值刷新为when
字段status
定时器状态
状态值常量有以下几个
Continue reading