Go 语言实现 23 种设计模式 单例模式
Go 語言實現 23 種設計模式 單例模式
單例模式
單例模式是一種常用的軟件設計模式,在使用過程中,單例對象的類只有一個實例。使用單例模式,1 可以節省內存等資源,例如windows操作系統的資源管理器只有一個就夠了。2 方便配置管理,例如,服務器的配置信息存放在一個文件中,配置信息由一個單例實例統一讀取,進場中的其他對象通過這個單例實例獲取配置信息。
實例1
下面這段代碼有什么問題,從多線程角度思考,就會發現下面的代碼是非線程安全的,比如有兩個線程都在調用NewInstance1函數,線程A在執行到if instance==nil后 cpu切換到線程B執行,直到線程B運行完,這時instance已經被實例化,當cpu在切回到線程A繼續執行的時候,對instance又執行實例化操作,這時內存中已有Instance的兩個實例,違背了單例定義。
type Instance struct{}//非線程安全 func NewInstance1() *Instance {if instance == nil {instance = &Instance{}}return instance }實例2
var lock sync.Mutex//lock-check模式 func NewInstance2() *Instance {lock.Lock()defer lock.Unlock()if instance == nil {instance = &Instance{}}return instance }實例3
實例3采用的是先判斷方式,如果instance已經被實例化,直接返回就行了。如果沒有實例化,在進行加鎖創建實例,即執行實例2的操作。這樣就可以并發執行。上面的實例2是先lock在check方式,簡稱lock-check模式,實例稱為check-lock-check模式。繼續思考,實例3有沒有問題呢?if instance==nil是原子操作嗎?
//check-lock-check模式 func NewInstance3() *Instance {if instance == nil {lock.Lock()if instance == nil {instance = &Instance{}}lock.Unlock()}return instance }實例4
既然實例3 比較操作是非原子操作,那將比較這句改成原子操作,golang 提供了原子操作package atomic,申請一個uint32變量做標記,如果是1表示已實例化,如果是0表示么有實例化。實例4已經非常好了,在golang有么有更好的方法呢,
var initlized uint32//check-lock-check func NewInstance4() *Instance {if atomic.LoadUint32(&initlized) == 1 {return instance}lock.Lock()defer lock.Unlock()if initlized == 0 {instance = &Instance{}atomic.StoreUint32(&initlized, 1)}return instance}實例5
在golang中,atomic包中提供一個sync.Once類型,該類型有個Do方法,只會執行一次,
所以將實例化方法放在Do中,只會實例化一次,非常完美的方法,所以實例5是最佳實踐方法。
分析總結
在寫代碼的時候,要保證正確性第一,然后在考慮性能優化的問題,實例1和實例3在正確性上沒有保證。
其次才是考慮性能優化,有沒有更好的方法,像實例2性能不友好,實例4就比實例2有提升,實例5是最佳實踐方法。
當然實例3方法可以放在init函數中調用,進程啟動之后再掉用其實也沒有問題,因為instance已經被實例化過了。
程序的運行中只產生一個實例
Example_one
type Singleton struct {id int }var TestSingleton *Singleton var singletonMutex sync.Mutexfunc NewSingleton() *Singleton {if TestSingleton == nil {singletonMutex.Lock()defer singletonMutex.Unlock()if TestSingleton == nil {TestSingleton = &Singleton{0}}}return TestSingleton }Example_two
func NewSingleton() *Singleton {once.Do(func() {TestSingleton = &Singleton{0}})return TestSingleton }總結
以上是生活随笔為你收集整理的Go 语言实现 23 种设计模式 单例模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 输卵管不孕怎么查
- 下一篇: Go 语言实现 23 种设计模式适配器