sync.Once
常應用于單例模式,例如初始化配置、保持資料庫連接等,
init函式通常是所在package首次被加載時執行,如果一直沒有被呼叫就會浪費記憶體,
sync.Once可以在代碼任意位置初始化和呼叫,因此可以延遲到使用時在執行,并發場景下時執行緒安全的,(類似于C#中的Lazy語法,懶加載)
在多數情況下,被用于控制變數的初始化,這個變數的讀寫滿足如下三個條件:
- 當且僅當第一次訪問某個變數時,進行初始化(寫);
- 變數初始化程序中所有都被阻塞,直到初始化完成;
- 變數僅初始化一次,初始化完成后駐留在記憶體內
原理:
Once結構體只有兩個欄位
type Once struct {
done uint32
m Mutex
}
sync.Once也只有一個Do方法用于初始化,內部實作就是簡單的兩點邏輯,①保證我們的變數僅會被初始化一次,原始碼中通過原子存取一個uint32來判斷是否是第一次初始化②保證執行緒安全并需要支持并發,所以當然這里使用鎖機制,
tip:
原始碼注釋中有描述到為何結構體中done是排在第一個,因為這樣可以將done在hot path中使用,hot path是程式非常頻繁執行的一系列指令,由于sync.Once在大部分場景下都會訪問到done,所以放在hot path上可以提升性能,并且結構體的第一個欄位的地址和結構體指標是相同的,也就是最常訪問的欄位放在第一個就在訪問時不需要計算偏移,減少CPU的偏移值的加法運算量,
參考:https://geektutu.com/post/hpg-sync-once.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/288199.html
標籤:其他
