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

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

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

一.sync.Once

Once(單次執(zhí)行)

用途:確保某個(gè)操作只執(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í)減少計(jì)數(shù)器
			loadConfig()
		}()
	}
	wg.Wait() // 等待所有 goroutine 完成
}

可以確保這個(gè)協(xié)程只進(jìn)行一次

二.sync.Cond

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

  • Wait():釋放鎖并阻塞,直到被喚醒。
  • Signal():?jiǎn)拘岩粋€(gè)等待的 goroutine。
  • Broadcast():?jiǎn)拘阉械却?goroutine。

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

type Cond struct {
    // 不可以對(duì)其進(jìn)行值拷貝
    noCopy noCopy
    // 一個(gè)自旋鎖
    L Locker
    // 一個(gè)隊(duì)列,存放阻塞的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,一把鎖,用于實(shí)現(xiàn)阻塞操作;

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

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)前這個(gè)持有鎖的goroutine,釋放鎖,陷入一個(gè)被動(dòng)阻塞的狀態(tài),加入阻塞隊(duì)列里面。

什么時(shí)候被喚醒呢?

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

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

使用的前置條件

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

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 是否在使用過(guò)后被拷貝,是則 panic;

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

(3)當(dāng)前協(xié)程釋放鎖,因?yàn)榻酉聛?lái)即將被 操作系統(tǒng) park;

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

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

2.3 Cond.Signal

作用:就是喚醒隊(duì)首的goroutine喚醒

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

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

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

(3)從頭開(kāi)始遍歷阻塞鏈表,喚醒一個(gè)等待時(shí)間最長(zhǎng)的 goroutine.

2.4 Cond.BroadCast

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

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

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

(2)取 wait 值賦值給 notify;

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

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() // 釋放鎖并阻塞,喚醒時(shí)會(huì)重新獲得鎖
			fmt.Println("等待者: 被喚醒,檢查條件")
		}
		fmt.Println("等待者: 條件已滿足!")
	}()
 
	// 改變條件的goroutine
	go func() {
		time.Sleep(2 * time.Second) // 模擬耗時(shí)操作
		fmt.Println("觸發(fā)者: 準(zhǔn)備改變條件...")
		
		cond.L.Lock()
		isReady = true
		cond.L.Unlock()
		
		fmt.Println("觸發(fā)者: 發(fā)送通知")
		cond.Signal() // 喚醒一個(gè)等待的goroutine
	}()
 
	time.Sleep(3 * time.Second) // 等待所有g(shù)oroutine完成
}

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

相關(guān)文章

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

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

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

    Golang中的強(qiáng)大Web框架Fiber詳解

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

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

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

    Goland使用delve進(jìn)行遠(yuǎn)程調(diào)試的詳細(xì)教程

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

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

    冒泡排序算法是數(shù)據(jù)結(jié)構(gòu)中常用的一種算法,本文就介紹了go實(shí)現(xiàn)冒泡排序算法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    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動(dòng)態(tài)庫(kù)函數(shù)

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

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

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

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

    golang中bufio.SplitFunc的深入理解

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

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

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

最新評(píng)論