成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Golang 常見設計模式之單例模式

開發
本文主要介紹Go語言中實現單例模式的幾種常用套路,經過對比可以得出結論,最推薦的方式是使用 once.Do 來實現,sync.Once 包幫我們隱藏了部分細節,卻可以讓代碼可讀性得到很大提升。

之前我們已經看過了 Golang 常見設計模式中的裝飾和選項模式,今天要看的是 Golang 設計模式里最簡單的單例模式。單例模式的作用是確保無論對象被實例化多少次,全局都只有一個實例存在。根據這一特性,我們可以將其應用到全局唯一性配置、數據庫連接對象、文件訪問對象等。Go 語言實現單例模式的方法有很多種,下面我們就一起來看一下。

餓漢式

餓漢式實現單例模式非常簡單,直接看代碼:

package singleton
type singleton struct{}
var instance = &singleton{}
func GetSingleton() *singleton {
return instance
}

singleton 包在被導入時會自動初始化 instance 實例,使用時通過調用 singleton.GetSingleton () 函數即可獲得 singleton 這個結構體的單例對象。

這種方式的單例對象是在包加載時立即被創建,所以這個方式叫作餓漢式。與之對應的另一種實現方式叫作懶漢式,懶漢式模式下實例會在第一次被使用時被創建。

需要注意的是,盡管餓漢式實現單例模式的方式簡單,但大多數情況下并不推薦。因為如果單例實例化時初始化內容過多,會造成程序加載用時較長。

懶漢式

接下來我們再來看下如何通過懶漢式實現單例模式:

package singleton
type singleton struct{}
var instance *singleton
func GetSingleton() *singleton {
if instance == nil {
instance = &singleton{}
}
return instance
}

相較于餓漢式的實現,懶漢式將實例化 singleton 結構體部分的代碼移到了 GetSingleton () 函數內部。這樣能夠將對象實例化的步驟延遲到 GetSingleton () 第一次被調用時。

不過通過 instance == nil 的判斷來實現單例并不十分可靠,如果有多個 goroutine 同時調用 GetSingleton () 就無法保證并發安全。

支持并發的單例

如果你使用 Go 語言寫過并發編程,應該很快能想到該如何解決懶漢式單例模式并發安全問題,比如像下面這樣:

package singleton
import "sync"
type singleton struct{}
var instance *singleton
var mu sync.Mutex
func GetSingleton() *singleton {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &singleton{}
}
return instance
}

上面代碼的修改是通過加鎖機制,即在 GetSingleton () 函數最開始加了如下兩行代碼:

mu.Lock()
defer mu.Unlock()

加鎖的機制可以有效保證這個實現單例模式的函數是并發安全的。

不過使用了鎖機制也帶來了一些問題,這讓每次調用 GetSingleton () 時程序都會進行加鎖、解鎖的步驟,從而導致程序性能的下降。

雙重鎖定

加鎖會導致程序性能下降,但又不用鎖又無法保證程序的并發安全。為了解決這個問題有人提出了雙重鎖定(Double-Check Locking)的方案:

package singleton
import "sync"
type singleton struct{}
var instance *singleton
var mu sync.Mutex
func GetSingleton() *singleton {
if instance == nil {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &singleton{}
}
}
return instance
}

通過上面的可以看到,所謂雙重鎖定實際上就是在程序加鎖前又加了一層 instance == nil 判斷,通過這種方式來兼顧性能和安全兩個方面。不過這讓代碼看起來有些奇怪,外層已經判斷了 instance == nil,但是加鎖后又進行了第二次 instance == nil 判斷。

其實外層的 instance == nil 判斷是為了提高程序的執行效率,免去原來每次調用 GetSingleton () 都上鎖的操作,將加鎖的粒度更加精細化。簡單說就是如果 instance 已經存在,則無需進入 if 邏輯,程序直接返回 instance 即可。而內層的 instance == nil 判斷則考慮了并發安全,考慮到萬一在極端情況下,多個 goroutine 同時走到了加鎖這一步,內層判斷會在這里起到作用。

Gopher 慣用方案

雖然雙重鎖定機制兼顧和性能和并發安全,但顯然代碼有些丑陋,不符合廣大 Gopher 的期待。好在 Go 語言在 sync 包中提供了 Once 機制能夠幫助我們寫出更加優雅的代碼:

package singleton
import "sync"
type singleton struct{}
var instance *singleton
var once sync.Once
func GetSingleton() *singleton {
once.Do(func() {
instance = &singleton{}
})
return instance
}

Once 是一個結構體,在執行 Do 方法的內部通過 atomic 操作和加鎖機制來保證并發安全,且 once.Do 能夠保證多個 goroutine 同時執行時 &singleton {} 只被創建一次。

其實 Once 并不神秘,其內部實現跟上面使用的雙重鎖定機制非常類似,只不過把 instance == nil 換成了 atomic 操作,感興趣的同學可以查看下其對應源碼。

總結

以上就是 Go 語言中實現單例模式的幾種常用套路,經過對比可以得出結論,最推薦的方式是使用 once.Do 來實現,sync.Once 包幫我們隱藏了部分細節,卻可以讓代碼可讀性得到很大提升。

責任編輯:趙寧寧 來源: 開源博客
相關推薦

2022-03-25 11:01:28

Golang裝飾模式Go 語言

2016-03-28 10:23:11

Android設計單例

2021-02-01 10:01:58

設計模式 Java單例模式

2015-09-06 11:07:52

C++設計模式單例模式

2021-03-02 08:50:31

設計單例模式

2013-11-26 16:20:26

Android設計模式

2022-02-06 22:30:36

前端設計模式

2024-02-04 12:04:17

2021-09-07 10:44:35

異步單例模式

2021-08-11 17:22:11

設計模式單例

2022-09-29 08:39:37

架構

2022-03-29 07:52:07

設計模式單例設計模式java

2024-03-06 13:19:19

工廠模式Python函數

2021-02-07 23:58:10

單例模式對象

2011-03-16 10:13:31

java單例模式

2020-08-21 07:23:50

工廠模式設計

2024-10-06 12:56:36

Golang策略設計模式

2015-01-14 13:26:58

AndroidJava單例

2023-03-21 15:21:52

開發程序設計static

2023-07-31 12:27:30

單例設計模式
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 毛片一级网站 | 国产精品久久久亚洲 | 亚洲有码转帖 | 亚洲一级视频在线 | 成人av一区 | 99综合网| 成人影院免费视频 | 国产一级片免费视频 | 亚洲免费人成在线视频观看 | 亚洲一区二区视频在线播放 | 韩日精品一区 | 日韩欧美一区二区三区四区 | 人人鲁人人莫人人爱精品 | 久久综合欧美 | 天天操天天插 | 在线观看黄视频 | 久久精品色视频 | 91精品国产综合久久小仙女图片 | 久久99蜜桃综合影院免费观看 | 国产一在线 | 国产成人精品一区二区三 | 亚洲电影专区 | 亚洲精品字幕 | 亚洲精品成人网 | 亚洲精品一区二区三区在线 | 亚洲视频免费在线看 | 乱一性一乱一交一视频a∨ 色爱av | 美女久久 | 亚洲国产精品va在线看黑人 | 成人午夜精品一区二区三区 | 四虎在线观看 | 久久精品国产久精国产 | 欧美在线观看一区二区 | av一二三区 | 欧美在线观看一区 | av在线免费观看网址 | 欧美日韩综合精品 | 精品久久久久久亚洲精品 | 九九久久久 | 欧美成人免费电影 | 爱爱免费视频 |