golang atomic load 性能_设计模式之Golang单例模式
今天給大家講下什么是單例模式,以及在Go語言中如何用正確的姿勢實現它。其實單例模式是一種在平時開發中經常用到的軟件設計模式。在設計模式結構中,其核心是只包含一個被稱為單例的特殊類。通過單例模式可以確保系統中一個類只有一個實例,且該實例容易被外界訪問,從而方便對實例數量的控制并節約系統資源。
1. 懶漢模式懶漢模式是平時軟件開發中比較常見的,也是用的最多的一種,該模式的最大缺點就是非線程安全。什么是非線程安全呢,這里就不展開講了,后續會單獨拿一期來講什么是線程安全和非線程安全。
懶漢模式代碼示例如下:
//?定義單例的結構體type?Singleton?struct?{}// 聲明一個Singleton結構體指針的變量var singleton *Singleton// 獲取單例的函數,返回Singleton結構體指針類型func GetSingleton() *Singleton { // 如果為空,則創建單例 if singleton == nil { singleton = &Singleton{} } return singleton}2. 帶普通鎖的單例模式上面講的懶漢模式,其實是沒有帶鎖的,也就是并發處理時會發生競爭,從而會導致程序出錯退出。
普通鎖可以解決并發處理帶來的問題,這里說的普通鎖其實是使用了Go的sync.Mutex,其缺點就是要人工維護鎖的添加和釋放,在有些時候對鎖的使用不當的話,反而會帶來不必要的性能消耗,事倍功半。?其工作原理類似于Linux內核的futex對象,具體實現原理這里就不詳細展開講來,sync.Mutex的原理后面也會單獨用一期來講。
帶普通鎖的單例模式示例代碼如下:
// 定義單例的結構體type Singleton2 struct {}// 聲明一個Singleton結構體指針的變量var instance *Singleton2// 聲明普通鎖變量,muvar mu sync.Mutex// 獲取帶鎖的單例函數func GetInstance() *Singleton2 { // 加鎖 mu.Lock() // 函數退出前解鎖 defer mu.Unlock() // 如果為空,則創建單例 if instance == nil { instance = &Singleton2{} } return instance}3. 比較優雅的單例模式以上兩鐘單例模式都有缺點,不是那么完美,而Golang本身sync.Once庫里就已經很好的實現了單例模式。
示例代碼如下:
// 創建一個結構體type?Manager?struct?{}// 聲明兩個全局變量,一個是Manager結構體指針,一個是用于單例等nocevar m *Managervar once sync.Once// 創建Manager單例函數func GetManage() *Manager {??//?once.Do已經優雅的封裝好了部分加鎖的代碼 once.Do(func() { m = &Manager{} }) return m}簡單來說,sync.Once表示只執行一次函數,要做到這點,需要有兩個條件:
計數器,統計函數執行的次數
線程安全,保證在多個goroutine(并發)情況下,函數仍然只執行一次,這里面其實也涉及到鎖
其中sync.Once實現的核心函數就是Do(),看一下Do函數的源碼,如下:
// Once源碼的數據結構type Once struct { m Mutex done uint32}// Do函數實現func (o *Once) Do(f func()) { if atomic.LoadUint32(&o.done) == 1 { return???} o.m.Lock() defer o.m.Unlock() if o.done == 0 { defer atomic.StoreUint32(&o.done, 1) f() }}根據以上的源碼可以看到是定義了Once結構體,其中的done成員就是用于統計函數執行的次數的,m成員是鎖,保障線程安全的。
Do方法也比較簡單:
首先原子操作load函數執行次數,如果已經執行過了,就return
然后lock加鎖
執行函數,原子操作store函數執行次數,賦值為1
解鎖unlock
如果換做是我們來寫的話,一般就會先直接加鎖,然后再比較函數執行的次數,而這里的源碼用了原子操作,這樣可以提高性能。總的來說,一些標志位可以通過原子操作來表示,從而避免加鎖,提高性能。
以上完整示例代碼已歸檔到我的github,如有需要歡迎下載學習交流:https://github.com/Scoefield/gokeyboardman/tree/main/singletonmode
本期設計模式之Golang單例模式的介紹就到這里啦,感謝您的閱讀,如有疑問或意見請及時反饋給我們。
上一篇文章:
Golang中的“包”
總結
以上是生活随笔為你收集整理的golang atomic load 性能_设计模式之Golang单例模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++编译过程
- 下一篇: net应用程序中发生了未经处理的异常怎么