亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

GoLang的sync.WaitGroup與sync.Once簡(jiǎn)單使用講解

 更新時(shí)間:2023年01月09日 11:07:31   作者:鯤鵬飛九萬(wàn)里  
sync.WaitGroup類(lèi)型,它比通道更加適合實(shí)現(xiàn)這種一對(duì)多的goroutine協(xié)作流程。WaitGroup是開(kāi)箱即用的,也是并發(fā)安全的。同時(shí),與之前提到的同步工具一樣,它一旦被真正的使用就不能被復(fù)制了

一、sync.WaitGroup的簡(jiǎn)單實(shí)用

在之前,我們使用通道,來(lái)主goroutine中等待其他goroutine執(zhí)行完成:

func coordinateWithChan() {
	sign := make(chan struct{}, 2)
	num := int32(0)
	fmt.Printf("The number: %d [with chan struct{}]\n", num)
	max := int32(10)
	go addNum(&num, 1, max, func() {
		sign <- struct{}{}
	})
	go addNum(&num, 2, max, func() {
		sign <- struct{}{}
	})
	<-sign
	<-sign
}

其實(shí),可以用更簡(jiǎn)單的方法,使用sync.WaitGroup來(lái)做:

func coordinateWithWaitGroup() {
	var wg sync.WaitGroup
	wg.Add(2)
	num := int32(0)
	fmt.Printf("The number: %d [with sync.WaitGroup]\n", num)
	max := int32(10)
	go addNum(&num, 3, max, wg.Done)
	go addNum(&num, 4, max, wg.Done)
	wg.Wait()
}

sync包的WaitGroup類(lèi)型。它比通道更加適合實(shí)現(xiàn)這種一對(duì)多的 goroutine 協(xié)作流程。

sync.WaitGroup類(lèi)型(以下簡(jiǎn)稱(chēng)WaitGroup類(lèi)型)是開(kāi)箱即用的,也是并發(fā)安全的。同時(shí),它一旦被真正使用就不能被復(fù)制了。

WaitGroup類(lèi)型擁有三個(gè)指針?lè)椒ǎ篈dd、Done和Wait。

Add方法

可以想象該類(lèi)型中有一個(gè)計(jì)數(shù)器,它的默認(rèn)值是0。我們可以通過(guò)調(diào)用該類(lèi)型值的Add方法來(lái)增加,或者減少這個(gè)計(jì)數(shù)器的值。

Done方法

用這個(gè)方法來(lái)記錄需要等待的 goroutine 的數(shù)量。相對(duì)應(yīng)的,這個(gè)類(lèi)型的Done方法,用于對(duì)其所屬值中計(jì)數(shù)器的值進(jìn)行減一操作。我們可以在需要等待的 goroutine 中,通過(guò)defer語(yǔ)句調(diào)用它。

Wait方法

此類(lèi)型的Wait方法的功能是,阻塞當(dāng)前的 goroutine,直到其所屬值中的計(jì)數(shù)器歸零。如果在該方法被調(diào)用的時(shí)候,那個(gè)計(jì)數(shù)器的值就是0,那么它將不會(huì)做任何事情。

二、sync.WaitGroup類(lèi)型值中計(jì)數(shù)器的值可以小于0嗎

不可以。

之所以說(shuō)WaitGroup值中計(jì)數(shù)器的值不能小于0,是因?yàn)檫@樣會(huì)引發(fā)一個(gè) panic。 不適當(dāng)?shù)卣{(diào)用這類(lèi)值的Done方法和Add方法都會(huì)如此。

  • 雖然WaitGroup值本身并不需要初始化,但是盡早地增加其計(jì)數(shù)器的值,還是非常有必要的。
  • WaitGroup值是可以被復(fù)用的,但需要保證其計(jì)數(shù)周期的完整性。
  • 不要把增加其計(jì)數(shù)器值的操作和調(diào)用其Wait方法的代碼,放在不同的 goroutine 中執(zhí)行。換句話(huà)說(shuō),要杜絕對(duì)同一個(gè)WaitGroup值的兩種操作的并發(fā)執(zhí)行。

三、sync.Once

sync.Once也屬于結(jié)構(gòu)體類(lèi)型,同樣也是開(kāi)箱即用和并發(fā)安全的。由于這個(gè)類(lèi)型包含了一個(gè)sync.Mutex類(lèi)型的字段,所以,復(fù)制該類(lèi)型的值也會(huì)導(dǎo)致功能的失效。

type Once struct {
	// done indicates whether the action has been performed.
	// It is first in the struct because it is used in the hot path.
	// The hot path is inlined at every call site.
	// Placing done first allows more compact instructions on some architectures (amd64/386),
	// and fewer instructions (to calculate offset) on other architectures.
	done uint32
	m    Mutex
}

用法

Once類(lèi)型的Do方法只接受一個(gè)參數(shù),這個(gè)參數(shù)的類(lèi)型必須是func(),即無(wú)參數(shù)聲明和結(jié)果聲明的函數(shù)。

該方法的功能并不是對(duì)每一種參數(shù)函數(shù)都只執(zhí)行一次,而是只執(zhí)行“首次被調(diào)用時(shí)傳入的”那個(gè)函數(shù),并且之后不會(huì)再執(zhí)行任何參數(shù)函數(shù)。

package main
import (
	"fmt"
	"sync"
	"sync/atomic"
)
func main() {
	var counter uint32
	var once sync.Once
	once.Do(func() {
		atomic.AddUint32(&counter, 1)
	})
	fmt.Printf("The counter: %d\n", counter)
	once.Do(func() {
		atomic.AddUint32(&counter, 2)
	})
	fmt.Printf("The counter: %v\n", counter)
	fmt.Println()
}

$ go run demo02.go
The counter: 1
The counter: 1

$

所以,如果你有多個(gè)只需要執(zhí)行一次的函數(shù),那么就應(yīng)該為它們中每一個(gè)都分配一個(gè)sync.Once類(lèi)型的值。

sync.Once類(lèi)型中的uint32類(lèi)型的字段

sync.Once類(lèi)型中有一個(gè)名叫done的uint32類(lèi)型的字段。它的作用是記錄其所屬值的Do方法被調(diào)用的次數(shù)。該字段的值只可能為0或1。

一旦Do方法首次調(diào)用完成,它的值就會(huì)從0變?yōu)?。

使用uint32 類(lèi)型是為了保證原子性。

修改done,使用了“雙重判斷+鎖”的方式,類(lèi)似于GoF設(shè)計(jì)模式中的單例模式。

func (o *Once) Do(f func()) {
	if atomic.LoadUint32(&o.done) == 0 {
		// Outlined slow-path to allow inlining of the fast-path.
		o.doSlow(f)
	}
}
func (o *Once) doSlow(f func()) {
	o.m.Lock()
	defer o.m.Unlock()
	if o.done == 0 {
		defer atomic.StoreUint32(&o.done, 1)
		f()
	}
}

Do方法的功能特點(diǎn)

第一個(gè)特點(diǎn):于Do方法只會(huì)在參數(shù)函數(shù)執(zhí)行結(jié)束之后把done字段的值變?yōu)?,因此,如果參數(shù)函數(shù)的執(zhí)行需要很長(zhǎng)時(shí)間或者根本就不會(huì)結(jié)束(比如執(zhí)行一些守護(hù)任務(wù)),那么就有可能會(huì)導(dǎo)致相關(guān) goroutine 的同時(shí)阻塞。

第二個(gè)特點(diǎn):Do方法在參數(shù)函數(shù)執(zhí)行結(jié)束后,對(duì)done字段的賦值用的是原子操作,并且,這一操作是被掛在defer語(yǔ)句中的。因此,不論參數(shù)函數(shù)的執(zhí)行會(huì)以怎樣的方式結(jié)束,done字段的值都會(huì)變?yōu)?。

也就是說(shuō),即使這個(gè)參數(shù)函數(shù)沒(méi)有執(zhí)行成功(比如引發(fā)了一個(gè) panic),我們也無(wú)法使用同一個(gè)Once值重新執(zhí)行它了。所以,如果你需要為參數(shù)函數(shù)的執(zhí)行設(shè)定重試機(jī)制,那么就要考慮Once值的適時(shí)替換問(wèn)題。

到此這篇關(guān)于GoLang的sync.WaitGroup與sync.Once簡(jiǎn)單使用講解的文章就介紹到這了,更多相關(guān)Go sync.WaitGroup與sync.Once內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang實(shí)現(xiàn)openssl自簽名雙向認(rèn)證的詳細(xì)步驟

    golang實(shí)現(xiàn)openssl自簽名雙向認(rèn)證的詳細(xì)步驟

    這篇文章主要介紹了golang實(shí)現(xiàn)openssl自簽名雙向認(rèn)證的詳細(xì)步驟,本文分步驟給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-03-03
  • goland服務(wù)熱重啟的配置文件

    goland服務(wù)熱重啟的配置文件

    這篇文章主要介紹了goland服務(wù)熱重啟的配置文件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • 詳解Golang如何實(shí)現(xiàn)一個(gè)環(huán)形緩沖器

    詳解Golang如何實(shí)現(xiàn)一個(gè)環(huán)形緩沖器

    環(huán)形緩沖器(ringr?buffer)是一種用于表示一個(gè)固定尺寸、頭尾相連的緩沖區(qū)的數(shù)據(jù)結(jié)構(gòu),適合緩存數(shù)據(jù)流。本文將利用Golang實(shí)現(xiàn)一個(gè)環(huán)形緩沖器,需要的可以參考一下
    2022-09-09
  • Go實(shí)踐反向代理ReverseProxy解析

    Go實(shí)踐反向代理ReverseProxy解析

    這篇文章主要為大家介紹了Go實(shí)踐反向代理示例ReverseProxy解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 詳解Go程序添加遠(yuǎn)程調(diào)用tcpdump功能

    詳解Go程序添加遠(yuǎn)程調(diào)用tcpdump功能

    這篇文章主要介紹了go程序添加遠(yuǎn)程調(diào)用tcpdump功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • Go語(yǔ)言基于HTTP的內(nèi)存緩存服務(wù)的實(shí)現(xiàn)

    Go語(yǔ)言基于HTTP的內(nèi)存緩存服務(wù)的實(shí)現(xiàn)

    這篇文章主要介紹了Go語(yǔ)言基于HTTP的內(nèi)存緩存服務(wù),本程序采用REST接口,支持設(shè)置(Set)、獲取(Get)和刪除(Del)這3個(gè)基本操作,同時(shí)還支持對(duì)緩存服務(wù)狀態(tài)進(jìn)行查詢(xún),需要的朋友可以參考下
    2022-08-08
  • GoLang內(nèi)存泄漏原因排查詳解

    GoLang內(nèi)存泄漏原因排查詳解

    內(nèi)存溢出是指程序在申請(qǐng)內(nèi)存時(shí),沒(méi)有足夠的內(nèi)存空間供其使用,簡(jiǎn)單點(diǎn)說(shuō)就是你要求分配的內(nèi)存超出了系統(tǒng)能給你的,系統(tǒng)不能滿(mǎn)足需求,于是產(chǎn)生溢出出現(xiàn)out of memory異常
    2022-12-12
  • 深入Go goroutine理解

    深入Go goroutine理解

    這篇文章主要介紹了深入Go goroutine理解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • 一個(gè)Pod調(diào)度失敗后重新觸發(fā)調(diào)度的所有情況分析

    一個(gè)Pod調(diào)度失敗后重新觸發(fā)調(diào)度的所有情況分析

    這篇文章主要為大家介紹了一個(gè)Pod調(diào)度失敗后重新觸發(fā)調(diào)度的所有情況分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Go語(yǔ)言學(xué)習(xí)之JSON編碼解析與使用

    Go語(yǔ)言學(xué)習(xí)之JSON編碼解析與使用

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中JSON編碼的解析與使用已經(jīng)JSON與Map、結(jié)構(gòu)體的互相轉(zhuǎn)化,文中的示例代碼講解詳細(xì),需要的可以參考一下
    2023-02-02

最新評(píng)論