日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Golang常見(jiàn)設(shè)計(jì)模式之單例模式

創(chuàng)新互聯(lián)建站是一家專注于網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì)與策劃設(shè)計(jì),洪澤網(wǎng)站建設(shè)哪家好?創(chuàng)新互聯(lián)建站做網(wǎng)站,專注于網(wǎng)站建設(shè)十年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:洪澤等地區(qū)。洪澤做網(wǎng)站價(jià)格咨詢:13518219792

餓漢式

餓漢式實(shí)現(xiàn)單例模式非常簡(jiǎn)單,直接看代碼:

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

singleton 包在被導(dǎo)入時(shí)會(huì)自動(dòng)初始化 instance 實(shí)例,使用時(shí)通過(guò)調(diào)用 singleton.GetSingleton () 函數(shù)即可獲得 singleton 這個(gè)結(jié)構(gòu)體的單例對(duì)象。

這種方式的單例對(duì)象是在包加載時(shí)立即被創(chuàng)建,所以這個(gè)方式叫作餓漢式。與之對(duì)應(yīng)的另一種實(shí)現(xiàn)方式叫作懶漢式,懶漢式模式下實(shí)例會(huì)在第一次被使用時(shí)被創(chuàng)建。

需要注意的是,盡管餓漢式實(shí)現(xiàn)單例模式的方式簡(jiǎn)單,但大多數(shù)情況下并不推薦。因?yàn)槿绻麊卫龑?shí)例化時(shí)初始化內(nèi)容過(guò)多,會(huì)造成程序加載用時(shí)較長(zhǎng)。

懶漢式

接下來(lái)我們?cè)賮?lái)看下如何通過(guò)懶漢式實(shí)現(xiàn)單例模式:

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

相較于餓漢式的實(shí)現(xiàn),懶漢式將實(shí)例化 singleton 結(jié)構(gòu)體部分的代碼移到了 GetSingleton () 函數(shù)內(nèi)部。這樣能夠?qū)?duì)象實(shí)例化的步驟延遲到 GetSingleton () 第一次被調(diào)用時(shí)。

不過(guò)通過(guò) instance == nil 的判斷來(lái)實(shí)現(xiàn)單例并不十分可靠,如果有多個(gè) goroutine 同時(shí)調(diào)用 GetSingleton () 就無(wú)法保證并發(fā)安全。

支持并發(fā)的單例

如果你使用 Go 語(yǔ)言寫(xiě)過(guò)并發(fā)編程,應(yīng)該很快能想到該如何解決懶漢式單例模式并發(fā)安全問(wèn)題,比如像下面這樣:

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
}

上面代碼的修改是通過(guò)加鎖機(jī)制,即在 GetSingleton () 函數(shù)最開(kāi)始加了如下兩行代碼:

mu.Lock()
defer mu.Unlock()

加鎖的機(jī)制可以有效保證這個(gè)實(shí)現(xiàn)單例模式的函數(shù)是并發(fā)安全的。

不過(guò)使用了鎖機(jī)制也帶來(lái)了一些問(wèn)題,這讓每次調(diào)用 GetSingleton () 時(shí)程序都會(huì)進(jìn)行加鎖、解鎖的步驟,從而導(dǎo)致程序性能的下降。

雙重鎖定

加鎖會(huì)導(dǎo)致程序性能下降,但又不用鎖又無(wú)法保證程序的并發(fā)安全。為了解決這個(gè)問(wèn)題有人提出了雙重鎖定(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
}

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

其實(shí)外層的 instance == nil 判斷是為了提高程序的執(zhí)行效率,免去原來(lái)每次調(diào)用 GetSingleton () 都上鎖的操作,將加鎖的粒度更加精細(xì)化。簡(jiǎn)單說(shuō)就是如果 instance 已經(jīng)存在,則無(wú)需進(jìn)入 if 邏輯,程序直接返回 instance 即可。而內(nèi)層的 instance == nil 判斷則考慮了并發(fā)安全,考慮到萬(wàn)一在極端情況下,多個(gè) goroutine 同時(shí)走到了加鎖這一步,內(nèi)層判斷會(huì)在這里起到作用。

Gopher 慣用方案

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

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 是一個(gè)結(jié)構(gòu)體,在執(zhí)行 Do 方法的內(nèi)部通過(guò) atomic 操作和加鎖機(jī)制來(lái)保證并發(fā)安全,且 once.Do 能夠保證多個(gè) goroutine 同時(shí)執(zhí)行時(shí) &singleton {} 只被創(chuàng)建一次。

其實(shí) Once 并不神秘,其內(nèi)部實(shí)現(xiàn)跟上面使用的雙重鎖定機(jī)制非常類似,只不過(guò)把 instance == nil 換成了 atomic 操作,感興趣的同學(xué)可以查看下其對(duì)應(yīng)源碼。

總結(jié)

以上就是 Go 語(yǔ)言中實(shí)現(xiàn)單例模式的幾種常用套路,經(jīng)過(guò)對(duì)比可以得出結(jié)論,最推薦的方式是使用 once.Do 來(lái)實(shí)現(xiàn),sync.Once 包幫我們隱藏了部分細(xì)節(jié),卻可以讓代碼可讀性得到很大提升。


本文名稱:Golang常見(jiàn)設(shè)計(jì)模式之單例模式
本文地址:http://m.5511xx.com/article/codgjip.html