1. 程式人生 > >Go 定時器內部實現原理剖析

Go 定時器內部實現原理剖析

前言

前面我們介紹了一次性定時器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