Go 定時器內部實現原理剖析
阿新 • • 發佈:2019-04-23
前言
前面我們介紹了一次性定時器Timer和週期性定時器Ticker,這兩種定時器內部實現機制相同。建立定時器的協程並不負責計時,而是把任務交給系統協程,系統協程統一處理所有的定時器。
本節,我們重點關注系統協程是如何管理這些定器的,包括以下問題:
- 定時器使用什麼資料結構儲存?
- 定時器如何觸發事件?
- 定時器如何新增進系統協程?
- 定時器如何從系統協程中刪除?
定時器儲存
timer資料結構
Timer和Ticker資料結構除名字外完全一樣,二者都含有一個runtimeTimer
型別的成員,這個就是系統協程所維護的物件。
runtimeTimer
型別是time
包的名稱,在runtime包中,這個型別叫做timer
timer
資料結構如下所示:
type timer struct { tb *timersBucket // the bucket the timer lives in // 當前定時器寄存於系統timer堆的地址 i int // heap index // 當前定時器寄存於系統timer堆的下標 when int64 // 當前定時器下次觸發時間 period int64 // 當前定時器週期觸發間隔(如果是Timer,間隔為0,表示不重複觸發) f func(interface{}, uintptr) // 定時器觸發時執行的函式 arg interface{} // 定時器觸發時執行函式傳遞的引數一 seq uintptr // 定時器觸發時執行函式傳遞的引數二(該引數只在網路收發場景下使用) }
其中timersBucket
便是系統協程儲存timer的地方,而i
便是timer儲存的下標。
timersBucket資料結構
儲存拓撲
(圖示,timer和tim