欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go單例模式與Once源碼實現

 更新時間:2022年12月08日 11:13:53   作者:如雨隨行2020  
這篇文章主要介紹了Go單例模式與Once源碼實現,本文結合示例代碼給大家講解的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

單例實現

type singleton struct{}

var (
	instance    *singleton
	initialized uint32
	mu          sync.Mutex
)

func Instance() *singleton {
	if atomic.LoadUint32(&initialized) == 1 {
		return instance
	}

	mu.Lock()
	defer mu.Unlock()

	if instance == nil {
		defer atomic.StoreUint32(&initialized, 1)
		instance = &singleton{}
	}
	return instance
}

其中通用的代碼提取出來,就成了標準庫中sync.Once的實現:

type Once struct {
	done uint32
	m    sync.Mutex
}

func (o *Once) Do(f func()) {
	if atomic.LoadUint32(&o.done) == 0 {

		o.m.Lock()
		defer o.m.Unlock()

		if o.done == 0 {
			defer atomic.StoreUint32(&o.done, 1)
			f()
		}
	}
}

于是,使用sync.Once重新實現單例模式

var (
	instance2 *singleton
	once sync.Once
)

func Instance2() *singleton {
	once.Do(func() {
		instance2 = &singleton{}
	})
	return instance2
}

sync.Once源碼分析

1. lock并不會同步值

在lock和unlock之間修改值,并不會保證對其他協程是可見的,除非使用相同的Mutex加鎖,想要同步值必須使用atomic;

lock可以通過串行化,使得兩個協程的操作存在happen-before關系,從而是的操作可見

happen-before原則定義如下:

如果一個操作happens-before(之前發(fā)生)另一個操作,那么第一個操作的執(zhí)行結果將對第二個操作可見,而且第一個操作的執(zhí)行順序排在第二個操作之前。

兩個操作之間存在happens-before關系,并不意味著一定要按照happens-before原則制定的順序來執(zhí)行。如果重排序之后的執(zhí)行結果與按照happens-before關系來執(zhí)行的結果一致,那么這種重排序并不非法。

2. Do執(zhí)行一次

當第一次執(zhí)行完Do之后,done設置成1,后面執(zhí)行Do會直接跳過

3. Once執(zhí)行Do后不準copy

A Once must not be copied after first use.

sync.Once執(zhí)行完Dodone已經設置成1了,copy出來的once執(zhí)行Do會直接跳過

4. Do并發(fā)時阻塞

當兩個或者多個協程同時調用Do時,先調用的協程執(zhí)行,后面的協程會阻塞;

解釋:以單例使用once的實現說明,兩個協程同時調用Instance2(),先調用的協程執(zhí)行創(chuàng)建并拿到返回值,后調用的阻塞,

? 等到先調用的完成后再拿到返回值;

意義:這樣的好處是防止后調用的協程拿到的是nil

源碼說明:上面第二段代碼13行使用defer,要等f()結束才會把done設置成1;其他協程并發(fā)調用Do時,done==0

? 然后請求m.Lock()形成阻塞

5. Do遞歸死鎖

如果Do中的方法調用當前once的Do會造成死鎖,原因參考上面一點(sync.Mutex.Lock()時不可重入鎖)

參考

  • 《Go語言高級編程》
  • Go1.16源碼

相關文章

  • 利用golang實現pdf中自動換行的表格

    利用golang實現pdf中自動換行的表格

    這篇文章主要給大家介紹了如何利用golang實現pdf中自動換行的表格,文中通過代碼示例給大家講解的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • go語言睡眠排序算法實例分析

    go語言睡眠排序算法實例分析

    這篇文章主要介紹了go語言睡眠排序算法,實例分析了睡眠排序算法的原理與實現技巧,需要的朋友可以參考下
    2015-03-03
  • Golang匯編命令解讀及使用

    Golang匯編命令解讀及使用

    這篇文章主要介紹了Golang匯編命令解讀及命令使用,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • 使用Go語言連接和操作數據庫的基本步驟

    使用Go語言連接和操作數據庫的基本步驟

    在Go語言中,連接和操作數據庫通常使用database/sql包,它提供了一個數據庫抽象層,支持多種數據庫引擎,如MySQL、PostgreSQL、SQLite等,下面我將以MySQL為例,詳細講解如何使用Go語言連接和操作數據庫,需要的朋友可以參考下
    2024-06-06
  • 利用go語言實現查找二叉樹中的最大寬度

    利用go語言實現查找二叉樹中的最大寬度

    這篇文章主要介紹了利用go語言實現查找二叉樹中的最大寬度,文章圍繞主題展開詳細介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-05-05
  • golang log4go的日志輸出優(yōu)化詳解

    golang log4go的日志輸出優(yōu)化詳解

    log4go源于google的一項log工程,但官方已經停止維護更新,下面這篇文章主要給大家介紹了關于golang log4go的日志輸出優(yōu)化的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-12-12
  • Go經典面試題匯總(填空+判斷)

    Go經典面試題匯總(填空+判斷)

    這篇文章主要介紹了Go經典面試題匯總(填空+判斷),本文章內容詳細,具有很好的參考價值,希望對大家有所幫助,需要的朋友可以參考下
    2023-01-01
  • 一文搞懂Go語言標準庫strconv

    一文搞懂Go語言標準庫strconv

    strconv包實現了基本數據類型和其字符串表示的相互轉換,本文主要介紹Go語言標準庫strconv,想要學習strconv標準庫的可以了解一下
    2023-04-04
  • 一文詳解Golang連接kafka的基本操作

    一文詳解Golang連接kafka的基本操作

    這篇文章主要為大家詳細介紹了Golang中連接kafka的基本操作的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2025-03-03
  • Go寫一個飛書機器人定時發(fā)送消息的項目實踐

    Go寫一個飛書機器人定時發(fā)送消息的項目實踐

    本文主要介紹了Go寫一個飛書機器人定時發(fā)送消息的項目實踐,需配置Webhook地址并確保機器人在群聊中,代碼每分鐘觸發(fā)一次,發(fā)送當前Unix時間戳消息,控制臺記錄調用日志與HTTP狀態(tài)碼
    2025-06-06

最新評論