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

Go語言sync.Once和sync.Cond的實現(xiàn)

 更新時間:2025年07月24日 10:43:57   作者:月憶364  
本文主要介紹了Go語言sync.Once和sync.Cond的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一.sync.Once

Once(單次執(zhí)行)

用途:確保某個操作只執(zhí)行一次(如初始化配置)

核心方法:Do(f func()):保證 f只執(zhí)行一次

package main
 
import (
	"fmt"
	"sync"
)
 
var (
	config map[string]string
	once   sync.Once
	wg     sync.WaitGroup
)
 
func loadConfig() {
	once.Do(func() {
		fmt.Println("Loading config...")
		config = map[string]string{"key": "value"}
	})
}
 
func main() {
	for i := 0; i < 5; i++ {
		wg.Add(1)
		go func() {
			defer wg.Done() // 確保 goroutine 結(jié)束時減少計數(shù)器
			loadConfig()
		}()
	}
	wg.Wait() // 等待所有 goroutine 完成
}

可以確保這個協(xié)程只進行一次

二.sync.Cond

sync.Cond 是 golang 標(biāo)準(zhǔn)庫提供的并發(fā)協(xié)調(diào)器,用于支援開放人員在指定條件下阻塞和喚醒協(xié)程的操作.

  • Wait():釋放鎖并阻塞,直到被喚醒。
  • Signal():喚醒一個等待的 goroutine。
  • Broadcast():喚醒所有等待的 goroutine。

2.1 數(shù)據(jù)結(jié)構(gòu)與構(gòu)造器方法

type Cond struct {
    // 不可以對其進行值拷貝
    noCopy noCopy
    // 一個自旋鎖
    L Locker
    // 一個隊列,存放阻塞的goroutine
    notify  notifyList
    checker copyChecker
}
 
// NewCond returns a new Cond with Locker l.
func NewCond(l Locker) *Cond {
    return &Cond{L:l}
}

(1)成員變量 noCopy + checker 是一套組合拳,保證 Cond 在第一次使用后不允許被復(fù)制;

(2)核心變量 L,一把鎖,用于實現(xiàn)阻塞操作;

(3)核心變量 notify,阻塞鏈表,分別存儲了調(diào)用 Cond.Wait() 方法的次數(shù)、goroutine 被喚醒的次數(shù)、一把系統(tǒng)運行時的互斥鎖以及鏈表的頭尾節(jié)點.

type notifyList struct {
    wait   uint32
    notify uint32
    lock   uintptr // key field of the mutex
    head   unsafe.Pointer
    tail   unsafe.Pointer
}

2.2 Cond.Wait

作用:把當(dāng)前這個持有鎖的goroutine,釋放鎖,陷入一個被動阻塞的狀態(tài),加入阻塞隊列里面。

什么時候被喚醒呢?

當(dāng)有其他的goroutine也持有這個Cond的引用,使用Signal函數(shù)的時候,會首先喚醒隊首的goroutine

通過這個機制就可以實現(xiàn)異步goroutine的協(xié)調(diào),比如需要某一個goroutine實現(xiàn)了某一個動作,另外一個goroutine才可以繼續(xù)執(zhí)行的一個場景。

使用的前置條件

看下面的代碼我們會發(fā)現(xiàn),它有一個解鎖的操作,所以在調(diào)用他之前,必須是加鎖的狀態(tài),只有這樣才可以執(zhí)行,然后陷入被動阻塞的狀態(tài),阻塞喚醒之后,才會重新加鎖。

func (c *Cond) Wait() {
    c.checker.check()
    t := runtime_notifyListAdd(&c.notify)
    c.L.Unlock()
    runtime_notifyListWait(&c.notify, t)
    c.L.Lock()
}

(1)檢查 Cond 是否在使用過后被拷貝,是則 panic;

(2)該 Cond 阻塞鏈表 wait 統(tǒng)計數(shù)加 1;

(3)當(dāng)前協(xié)程釋放鎖,因為接下來即將被 操作系統(tǒng) park;

(4)將當(dāng)前協(xié)程包裝成節(jié)點,添加到 Cond 的阻塞隊列當(dāng)中,并調(diào)用 park 操作將當(dāng)前協(xié)程掛起;

(5)協(xié)程被喚醒后,重新嘗試獲取鎖.

2.3 Cond.Signal

作用:就是喚醒隊首的goroutine喚醒

func (c *Cond) Signal() {
    c.checker.check()
    runtime_notifyListNotifyOne(&c.notify)
}

(1)檢查 Cond 是否在首次使用后被拷貝,是則 panic;

(2)該 Cond 阻塞鏈表 notify 統(tǒng)計數(shù)加 1;

(3)從頭開始遍歷阻塞鏈表,喚醒一個等待時間最長的 goroutine.

2.4 Cond.BroadCast

作用:就是將阻塞隊列里面的所有g(shù)oroutine都進行喚醒。

func (c *Cond) Broadcast() {
    c.checker.check()
    runtime_notifyListNotifyAll(&c.notify)
}

(1)檢查 Cond 是否在首次使用后被拷貝,是則 panic;

(2)取 wait 值賦值給 notify;

(3)喚醒阻塞鏈表所有節(jié)點.

2.5 使用案例

package main
 
import (
	"fmt"
	"sync"
	"time"
)
 
func main() {
	var mu sync.Mutex
	cond := sync.NewCond(&mu)
	
	// 共享狀態(tài)
	isReady := false
 
	// 等待條件的goroutine
	go func() {
		fmt.Println("等待者: 等待條件滿足...")
		cond.L.Lock()
		defer cond.L.Unlock()
		
		// 使用循環(huán)防止虛假喚醒
		for !isReady {
			cond.Wait() // 釋放鎖并阻塞,喚醒時會重新獲得鎖
			fmt.Println("等待者: 被喚醒,檢查條件")
		}
		fmt.Println("等待者: 條件已滿足!")
	}()
 
	// 改變條件的goroutine
	go func() {
		time.Sleep(2 * time.Second) // 模擬耗時操作
		fmt.Println("觸發(fā)者: 準(zhǔn)備改變條件...")
		
		cond.L.Lock()
		isReady = true
		cond.L.Unlock()
		
		fmt.Println("觸發(fā)者: 發(fā)送通知")
		cond.Signal() // 喚醒一個等待的goroutine
	}()
 
	time.Sleep(3 * time.Second) // 等待所有g(shù)oroutine完成
}

到此這篇關(guān)于Go語言sync.Once和sync.Cond的實現(xiàn)的文章就介紹到這了,更多相關(guān)Go語言sync.Once和sync.Cond內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang 實現(xiàn)并發(fā)求和

    golang 實現(xiàn)并發(fā)求和

    這篇文章主要介紹了golang 并發(fā)求和的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Golang中的強大Web框架Fiber詳解

    Golang中的強大Web框架Fiber詳解

    在不斷發(fā)展的Web開發(fā)領(lǐng)域中,選擇正確的框架可以極大地影響項目的效率和成功,介紹一下Fiber,這是一款令人印象深刻的Golang(Go語言)Web框架,在本文中,我們將深入了解Fiber的世界,探討其獨特的特性,并理解為什么它在Go生態(tài)系統(tǒng)中引起了如此大的關(guān)注
    2023-10-10
  • Golang實現(xiàn)組合模式和裝飾模式實例詳解

    Golang實現(xiàn)組合模式和裝飾模式實例詳解

    這篇文章主要介紹了Golang實現(xiàn)組合模式和裝飾模式,本文介紹組合模式和裝飾模式,golang實現(xiàn)兩種模式有共同之處,但在具體應(yīng)用場景有差異。通過對比兩個模式,可以加深理解,需要的朋友可以參考下
    2022-11-11
  • Goland使用delve進行遠程調(diào)試的詳細教程

    Goland使用delve進行遠程調(diào)試的詳細教程

    網(wǎng)上給出的使用delve進行遠程調(diào)試,都需要先在本地交叉編譯或者在遠程主機上編譯出可運行的程序,然后再用delve在遠程啟動程序,本教程會將上面的步驟簡化為只需要兩步,1,在遠程運行程序2,在本地啟動調(diào)試,需要的朋友可以參考下
    2024-08-08
  • go實現(xiàn)冒泡排序算法

    go實現(xiàn)冒泡排序算法

    冒泡排序算法是數(shù)據(jù)結(jié)構(gòu)中常用的一種算法,本文就介紹了go實現(xiàn)冒泡排序算法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Golang學(xué)習(xí)之內(nèi)存逃逸分析

    Golang學(xué)習(xí)之內(nèi)存逃逸分析

    內(nèi)存逃逸分析是go的編譯器在編譯期間,根據(jù)變量的類型和作用域,確定變量是堆上還是棧上。本文將帶大家分析一下Golang中的內(nèi)存逃逸,需要的可以了解一下
    2023-01-01
  • go如何調(diào)用C動態(tài)庫函數(shù)

    go如何調(diào)用C動態(tài)庫函數(shù)

    這篇文章主要介紹了go如何調(diào)用C動態(tài)庫函數(shù)的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • 基于Go語言實現(xiàn)選擇排序算法及優(yōu)化

    基于Go語言實現(xiàn)選擇排序算法及優(yōu)化

    選擇排序是一種簡單的比較排序算法.這篇文章將利用Go語言實現(xiàn)冒泡排序算法,文中的示例代碼講解詳細,對學(xué)習(xí)Go語言有一定的幫助,需要的可以參考一下
    2022-12-12
  • golang中bufio.SplitFunc的深入理解

    golang中bufio.SplitFunc的深入理解

    這篇文章主要給大家介紹了關(guān)于golang中bufio.SplitFunc的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用golang具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-10-10
  • golang中的select關(guān)鍵字用法總結(jié)

    golang中的select關(guān)鍵字用法總結(jié)

    這篇文章主要介紹了golang中的select關(guān)鍵字用法總結(jié),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06

最新評論