Golang 單例模式實現


單例模式在開發中是一種相對簡單的設計模式,但它在實現上又有很多種方式

熟悉java的同學知道在java中實現單例常見的有懶漢式、餓漢式、雙重檢查、內部靜態類、枚舉單例等(傳送門

而由於語言的特性,golang目前常見的有以下四種方式(懶漢式、餓漢式、雙重檢查、sync.Once)

1.懶漢式----非線程安全

非線程安全,即在多線程下可能會創建多次對象

/**
 * 使用結構體代替類
 */
type Tool struct {
    values int
}

/**
 * 建立私有變量
 */
var instance *Tool

/**
 * 獲取單例對象的方法,引用傳遞返回
 */
func GetInstance() *Tool {
    if instance == nil {
        instance = new(Tool)
    }

    return instance
}

 

2.懶漢式----線程安全

在非線程安全的基本上,利用Sync.Mutex進行加鎖,保證線程安全,但由於每次調用該方法都進行了加鎖操作,在性能上相對不高效

/**
 * 鎖對象
 */
var lock sync.Mutex

/**
 * 加鎖保證線程安全
 */
func GetInstance() *Tool {
    lock.Lock()
    defer lock.Unlock()
    if instance == nil {
        instance = new(Tool)
    }

    return instance
}

 

3.餓漢式

直接創建好對象,這樣不需要判斷為空,同時也是線程安全。唯一的缺點是在導入包的同時會創建該對象,並持續占有在內存中。

var instance Tool

func GetInstance() *Tool {
    return &instance
}

 

4.雙重檢查

在懶漢式(線程安全)的基礎上再進行憂化,判少加鎖的操作。保證線程安全同時不影響性能

/**
* 鎖對象
*/
var lock sync.Mutex

/**
* 第一次判斷不加鎖,第二次加鎖保證線程安全,一旦對象建立后,獲取對象就不用加鎖了
*/
func GetInstance() *Tool {
    if instance == nil {
        lock.Lock()

        if instance == nil {
            instance = new(Tool)
        }

        lock.Unlock()
    }

    return instance
}

 

5.sync.Once

通過sync.Once 來確保創建對象的方法只執行一次

var once sync.Once

func GetInstance() *Tool {
    once.Do(func() {
        instance = new(Tool)

    })
    return instance
}

sync.Once內部本質上也是雙重檢查的方式,但在寫法上會比自己寫雙重檢查更簡潔,以下是Once的源碼

func (o *Once) Do(f func()) {
   //判斷是否執行過該方法,如果執行過則不執行
if atomic.LoadUint32(&o.done) == 1 { return } // Slow-path. o.m.Lock() defer o.m.Unlock()
  //進行加鎖,再做一次判斷,如果沒有執行,則進行標志已經掃行並調用該方法
if o.done == 0 { defer atomic.StoreUint32(&o.done, 1) f() } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM