当前位置:网站首页>Important knowledge of golang: timer timer
Important knowledge of golang: timer timer
2022-06-23 15:24:00 【yue_ xin_ tech】
Abstract
stay Go There are many ways to use timers in , Like regular Timer、Ticker object , And what you often see time.After(d Duration) and time.Sleep(d Duration) Method , Today we will introduce their usage and analyze their underlying source code , In order to use the timer in better scenarios .
Go The timer in the room
Let's take a look first Timer object as well as time.After Method , They all have the feature of one-time use . about Timer Come on , After using it, you can enable it again , Just call its Reset Method .
// Timer Example
func main() {
myTimer := time.NewTimer(time.Second * 5) // Start timer
for {
select {
case <-myTimer.C:
dosomething()
myTimer.Reset(time.Second * 5) // It needs to be reset manually after each use
}
}
// No longer use , End it
myTimer.Stop()
}
// time.After Example
func main() {
timeChannel := time.After(10 * time.Second)
select {
case <-timeChannel:
doSomething()
}
}
You can see that from the top Timer Allow to be enabled again , and time.After Back to a channel, Will not be reusable .
And it's important to note that time.After Essentially, it creates a new Timer Structure , It's just that what is exposed is in the structure channel It's just a field .
So if the for{...} It is recycled in time.After, Will continue to create Timer. The following usage methods will cause performance problems :
// Wrong case !!!
func main() {
for {
// for Inside time.After Will continue to create Timer object
select {
case <-time.After(10 * time.Second):
doSomething()
}
}
}
After reading it, I have “ Primary characteristics ” Timer for , Next, let's take a look at the timer that repeats the task at certain intervals :
func main() {
ticker := time.NewTicker(3 * time.Second)
for {
<-ticker.C
doSomething()
}
ticker.Stop()
}
there Ticker Follow Timer The difference , It's about Ticker There is no need to call after the time Reset Method , Will automatically renew .
In addition to the timer above ,Go Inside time.Sleep It also has a timing function similar to one-time use . It's just time.Sleep System call is used . Timers like the one above rely more on Go The scheduling behavior of .
Realization principle
When we go through NewTimer、NewTicker And so on , Back to a Timer object . There is one in this object runtimeTimer The structure of the field , It will eventually be compiled into src/runtime/time.go Inside timer Structure .
And this timer A structure is a structure with real timing processing logic .
In limine ,timer Will be assigned to a global timersBucket Time bucket . Whenever there is timer When created , Will be allocated to the corresponding time bucket .
In order not to let all timer All in one time bucket ,Go Will create 64 Such a time bucket , And then according to At present timer Where Goroutine Of P Of id Go hash to a bucket :
// assignBucket Will create the timer Linked to a bucket
func (t *timer) assignBucket() *timersBucket {
id := uint8(getg().m.p.ptr().id) % timersLen
t.tb = &timers[id].timersBucket
return t.tb
}
next timersBucket The time bucket will be for these timer Maintain a minimum heap , Each time, I will choose the one that the time is closest to reaching timer.
If the selected timer It's not time yet , Then it will go on sleep Sleep .
If timer It's time to , execute timer The function on , And go to timer Of channel Field send data , In order to inform timer Where goroutine.
Source code analysis
The principle of the lower timer is mentioned above , Now let's take a good look at the timer timer Source code .
First , When timer is created , Would call startTimer Method :
func startTimer(t *timer) {
if raceenabled {
racerelease(unsafe.Pointer(t))
}
// 1. Start putting the current timer Add to In the time bucket
addtimer(t)
}
and addtimer That is what we just said about the action of allocating to a bucket :
func addtimer(t *timer) {
tb := t.assignBucket() // Allocate to a time bucket
lock(&tb.lock)
ok := tb.addtimerLocked(t) // 2. After adding , The time bucket performs a heap sort , Pick the nearest timer To carry out
unlock(&tb.lock)
if !ok {
badTimer()
}
}
addtimerLocked Contains the final time processing function : timerproc, Focus on the analysis of :
// When there is a new timer Triggered once when added
// When the last time to sleep comes , It will also trigger once
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 {
delta = -1
break
}
t := tb.t[0]
delta = t.when - now
if delta > 0 {
// The timer is not up yet
break
}
ok := true
if t.period > 0 {
// here period > 0, Said is ticker Type of timer ,
// Reset the time of the next call , help ticker Automatic renewal
t.when += t.period * (1 + -delta/t.period)
if !siftdownTimer(tb.t, 0) {
ok = false
}
} else {
// “ Disposable ” Timer , And it's time , It needs to be removed first , Then do the following actions
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 {
if !siftdownTimer(tb.t, 0) {
ok = false
}
}
t.i = -1 // Mark cleared
}
// This indicates that the timer time has expired , You need to execute the corresponding function .
// This function is just sendTime, It will go there timer Of channel send data ,
// To notify the corresponding goroutine
f := t.f
arg := t.arg
seq := t.seq
unlock(&tb.lock)
if !ok {
badTimer()
}
if raceenabled {
raceacquire(unsafe.Pointer(t))
}
f(arg, seq)
lock(&tb.lock)
}
if delta < 0 || faketime > 0 {
// There is no timer to perform tasks , use gopark Sleep
// No timers left - put goroutine to sleep.
tb.rescheduling = true
goparkunlock(&tb.lock, waitReasonTimerGoroutineIdle, traceEvGoBlock, 1)
continue
}
// Yes timer But it's not time yet , So we use notetsleepg Sleep
tb.sleeping = true
tb.sleepUntil = now + delta
noteclear(&tb.waitnote)
unlock(&tb.lock)
notetsleepg(&tb.waitnote, delta)
}
}
In the code above , I found that there was no timer in the time bucket ,goroutine Would call gopark De dormancy , Until there is a new one timer Add to time bucket , To recall the loop code that executes the timer .
in addition , When the timer selected by heap sorting has not expired , It will call notetsleepg To sleep , Wait until the hibernation time is up and be aroused again .
summary
Go The timer uses heap sorting to pick the most recent timer, And will go to timer Of channel Field send data , To notify the corresponding goroutine So let's keep going .
This is the basic principle of timer , Other processes are just the execution of sleep arousal , I hope this article can help you to Go The understanding of timers !!!
Interested friends can search the official account 「 Read new technology 」, Pay attention to more push articles .
If you can , Just like it by the way 、 Leave a message 、 Under the share , Thank you for your support !
Read new technology , Read more new knowledge .
边栏推荐
- The team of China University of Mines developed an integrated multi-scale deep learning model for RNA methylation site prediction
- JS创建一个数组(字面量)
- HCIA 网络基础
- Half wave loss equal thickness and equal inclination interference
- 30. 串联所有单词的子串
- golang--判断字符串是否相等
- SFOD:无源域适配升级优化,让检测模型更容易适应新数据(附论文下载)
- 快速排序的簡單理解
- 杀入美团、饿了么腹地,京东外卖劲儿有多大?
- Raspberry PI installing the wiring pi
猜你喜欢

Half wave loss equal thickness and equal inclination interference

Simple tutorial of live streaming with OBS

Why is Xiaomi stuck in the chip quagmire?

这届文娱人,将副业做成了主业

An idea plug-in for automatically generating unit tests

General sequence representation learning in kdd'22 "Ali" recommendation system

SQL injection vulnerability (principle)

百萬獎金等你來拿,首届中國元宇宙創新應用大賽聯合創業黑馬火熱招募中!

labelme的JSON文件转成COCO数据集格式

从3开始,在业务系统中增加分页功能
随机推荐
小米为何深陷芯片泥潭?
k8s--部署单机版MySQL,并持久化
mysql 系列:总体架构概述
js中的push函数介绍
The well-known face search engine provokes public anger: just one photo will strip you of your pants in a few seconds
Converging ecology, enabling safe operation, Huawei cloud security, cloud brain intelligent service security
After nine years at the helm, the founding CEO of Allen Institute retired with honor! He predicted that Chinese AI would lead the world
微信小程序引导用户添加小程序动画页
信贷产品额度定价场景下的回归模型效果评估
2021-05-08
JS的unshift()和shift()
The team of China University of Mines developed an integrated multi-scale deep learning model for RNA methylation site prediction
Horizon development board commissioning
The principle of redis cache consistency deep analysis
F5《2022年应用策略现状报告》:边缘部署及负载安全成亚太地区关注焦点
mysql主从只同步部分库或表的思路与方法
The new version of Alibaba Seata finally solves the idempotence, suspension and empty rollback problems of the TCC mode
An idea plug-in for automatically generating unit tests
AXI_ Round_ Robin_ Arbiter design - aw and W channels
idea查看.class文件 idea查看.class文件夹