【go基础】15.定时器Timer, Ticker

目录

定时器底层结构的发展过程

数据结构

状态机

计时器的触发

Timer和Ticker使用


参考:Go 语言并发编程与计时器 | Go 语言设计与实现

定时器底层结构的发展过程


1. go 1.10之前,全局四叉堆

使用最小四叉堆。由于全局四叉堆共用互斥锁,锁竞争影响性能。

2. go 1.10-1.13,全局64个四叉堆

将全局四叉堆分成64个更小的四叉堆,每个处理器(P)创建的计时器由对应的四叉堆维护

这种分片方式降低了锁粒度,提高了性能,但是造成了cpu频繁上下文切换。

3. go 1.14之后,每个处理器单独管理计时器,并通过网络轮询器触发

每个P拥有一个最小四叉堆,单独管理。交给网络轮询器和调度器触发,较少上下文切换开销。

数据结构


type p struct {
        timersLock    mutex
        timers        []*timer   // 每个p拥有一个timers,即存储计时器的最小四叉堆

        numTimers     uint32
        adjustTimers  uint32
        deletedTimers uint32
        ...
}
type timer struct {
        pp puintptr

        when     int64  //当前计时器被唤醒的时间
        period   int64  //两次被唤醒的间隔
        f        func(interface{}, uintptr)  //每当计时器被唤醒时都会调用的函数
        arg      interface{}                 //计时器被唤醒时调用 f 传入的参数
        seq      uintptr
        nextwhen int64    //计时器处于 timerModifiedXX 状态时,用于设置 when 字段
        status   uint32   //计时器的状态
}

对外暴露的Timer结构体:

type Timer struct {
        C <-chan Time
        r runtimeTimer
}

状态机


10种状态:
  • timerNoStatus:还未设置状态
  • timerWaiting:等待触发
  • timerRunning:运行计时器函数
  • timerDeleted:被删除
  • timerRemoving:正在被删除
  • timerRemoved:已经被停止并从堆中删除
  • timerModifying:正在被修改
  • timerModifiedEarlier:被修改到了更早的时间
  • timerModifiedLater:被修改到了更晚的时间
  • timerMoving:已经被修改正在被移动
动作:
  • 增加计时器
  • 删除计时器
  • 修改计时器
  • 清除计时器
  • 调整计时器
  • 运行计时器

计时器的触发


go会在两个模块触发计时器,运行计时器中的函数:

1. 调度器

调度器会检查计时器是否准备就绪。

运行计时器函数的时机:

  • 调度器调用 runtime.schedule 执行调度时
  • 调度器调用 runtime.findrunnable 获取可执行的goroutine 或从其他处理器窃取计时器时

2. 系统监控

后台系统监控(函数runtine.sysmon)会检查是否有未执行的到期计时器。

Timer和Ticker使用


1. timer

ch := make(chan int, 1)
go func() {
    time.Sleep(2 * time.Second)
    ch <- 1
}()

timer := time.NewTimer(1 * time.Second)
select {
case <-ch:
    fmt.Println("Got response.")
case <-timer.C:
    fmt.Println("Timeout.”)  // 会进到这里超时
}
2. ticker
// 每隔1s执行一次
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for {
    select {
    case <-ticker.C:
        fmt.Println("task triggered")    
    }
}

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值