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

詳解Golang并發(fā)控制的三種方案

 更新時(shí)間:2024年06月19日 09:12:00   作者:拔劍縱狂歌  
本文主要介紹了詳解Golang并發(fā)控制的三種方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

Channel

Channel是Go在語(yǔ)言層面提供的一種協(xié)程間的通信方式,我們可以通過(guò)在協(xié)程中向管道寫(xiě)入數(shù)據(jù)和在待等待的協(xié)程中讀取對(duì)應(yīng)協(xié)程的次數(shù)來(lái)實(shí)現(xiàn)并發(fā)控制。

func main() {
    intChan := make(chan int, 5)
    waitCount := 5
    for i := 0; i < waitCount; i++ {
       go func() {
          intChan <- 1
       }()
    }

    for i := 0; i < waitCount; i++ {
       <-intChan

    }
    fmt.Println("主進(jìn)程結(jié)束")
}

WaitGroup

waitgroup通常應(yīng)用于等待一組“工作協(xié)程”結(jié)束的場(chǎng)景,waitgroup底層是由一個(gè)長(zhǎng)度為3的數(shù)組實(shí)現(xiàn)的,其內(nèi)部有兩個(gè)計(jì)數(shù)器,一個(gè)是工作協(xié)程計(jì)數(shù)器、一個(gè)是坐等協(xié)程計(jì)數(shù)器,還有一個(gè)是信號(hào)量。工作協(xié)程全部運(yùn)行結(jié)束后,工作協(xié)程計(jì)數(shù)器將置為0,會(huì)釋放對(duì)應(yīng)坐等協(xié)程次數(shù)的信號(hào)量。

兩點(diǎn)注意:

  • Add()方法中的參數(shù)大小要于工作協(xié)程的數(shù)量相等,否則會(huì)導(dǎo)致坐等協(xié)程一直等待,觸發(fā)死鎖panic

  • Done()方法執(zhí)行的次數(shù)要與Add()方法中的工作協(xié)程計(jì)數(shù)器的數(shù)量一致,否則當(dāng)工作協(xié)程計(jì)數(shù)器<0時(shí),會(huì)觸發(fā)panic【panic: sync: negative WaitGroup counter】

func main() {
    wg := sync.WaitGroup{}
    wg.Add(2)
    go func() {
       time.Sleep(3 * time.Second)
       fmt.Println("等待三分鐘的協(xié)程結(jié)束了")
       wg.Done()
    }()

    go func() {
       time.Sleep(3 * time.Second)
       fmt.Println("等待三分鐘的協(xié)程結(jié)束了")
       wg.Done()
    }()

    wg.Wait()
}

Context

適用于一個(gè)協(xié)程派生出多個(gè)協(xié)程的情況,可以控制多級(jí)的goroutine。我們可以通過(guò)一個(gè)Context對(duì)象,對(duì)派生出來(lái)的樹(shù)狀goroutine進(jìn)行統(tǒng)一管理,并且每個(gè)goroutine具有相同的上下文。做統(tǒng)一關(guān)閉操作、統(tǒng)一定時(shí)關(guān)閉、統(tǒng)一傳值的操作。多個(gè)上下文協(xié)程之間可以互相嵌套配合。

golang實(shí)現(xiàn)了四種原生的上下文對(duì)象

  • emptyCtx: 該上下文對(duì)象一般是作為父節(jié)點(diǎn)的,如果沒(méi)有父節(jié)點(diǎn),我們通常使用context.Background()方法來(lái)獲取emptyCtx對(duì)象,并將其作為創(chuàng)建其他節(jié)點(diǎn)的父節(jié)點(diǎn)。

  • cancelCtx: 該上下文對(duì)象可以關(guān)閉所有擁有同一個(gè)上下文的goroutine,通過(guò)在子協(xié)程中監(jiān)聽(tīng)cancelCtx.Done方法,來(lái)結(jié)束所有的派生協(xié)程。具體代碼看下方,我們通過(guò)WithCancel()方法來(lái)獲取該對(duì)象。

  • timerCtx:該上下文對(duì)象是對(duì)cancelCtx對(duì)象的進(jìn)一步封裝,比cancelCtx主動(dòng)關(guān)閉之外,多了了一個(gè)定時(shí)關(guān)閉功能。我們可以通過(guò)WithTimeout()和WithDeadline()這兩種方法來(lái)獲取該對(duì)象。其中WithTimeout()和WithDeadline()這兩種方法點(diǎn)是WithTimeout()是設(shè)置過(guò)一段時(shí)間關(guān)閉上下文,WithDeadline()是設(shè)置那一個(gè)時(shí)間點(diǎn)來(lái)關(guān)閉這一個(gè)上下文。

  • valueCtx:該上下文對(duì)象并不用于進(jìn)行協(xié)程的控制,而是在多級(jí)協(xié)程之間進(jìn)行值得傳遞,方便共享一些相同得上下文內(nèi)容。

以上除emptyCtx外的上下文對(duì)象和獲取實(shí)例的方法如下圖所示:

 Context示例代碼

cancelCtx

我們?cè)谒械呐缮鷧f(xié)程中傳入相同的cancelContext對(duì)象,并在每一個(gè)子協(xié)程中使用switch-case結(jié)構(gòu)監(jiān)聽(tīng)上下文對(duì)象是否關(guān)閉,如果上下文對(duì)象關(guān)閉了,ctx.Done()返回的管道就可以讀取到一個(gè)元素,使所在的case語(yǔ)句可執(zhí)行,之后退出switch結(jié)構(gòu),執(zhí)行協(xié)程中的其他代碼。

func main() {
	ctx, cancelFunc := context.WithCancel(context.Background())
	deadline, ok := ctx.Deadline()
	fmt.Println(deadline, ok)
	done := ctx.Done()
	fmt.Println(reflect.TypeOf(done))
	fmt.Println(done)

	go HandelRequest(ctx)
	//<-done 阻塞當(dāng)前一層的goroutine
	time.Sleep(5 * time.Second)
	fmt.Println("all goroutines is stopping!")
	cancelFunc()
	err := ctx.Err()
	fmt.Println(err) //context canceled
	time.Sleep(5 * time.Second)
}

func HandelRequest(ctx context.Context) {
	go WriteMysql(ctx)
	go WriteRedis(ctx)
	for {
		select {
		case <-ctx.Done():
			fmt.Println("HandelRequest Done")
			return
		default:
			fmt.Println("等一等,Handler正在執(zhí)行中")
			time.Sleep(2 * time.Second)
		}
	}
}

func WriteRedis(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("WriteRedis Done.")
			return
		default:
			fmt.Println("等一等,Redis正在執(zhí)行中")
			time.Sleep(2 * time.Second)
		}
	}
}

func WriteMysql(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("WriteMysql Done.")
			return
		default:
			fmt.Println("等一等,Mysql正在執(zhí)行中")
			time.Sleep(2 * time.Second)
		}
	}
}

timerCtx

這里代碼以WithTimeout舉例,相比與我們之前的手動(dòng)調(diào)用關(guān)閉,使用timerCtx定時(shí)上下文對(duì)象后,可以是實(shí)現(xiàn)到達(dá)指定的時(shí)間自動(dòng)進(jìn)行關(guān)閉的操作。

func main() {
	deadline, _ := context.WithTimeout(context.Background(), 5*time.Second)
	go HandelRequest(deadline)

	time.Sleep(10 * time.Second)

}

func HandelRequest(ctx context.Context) {
	go WriteMysql(ctx)
	go WriteRedis(ctx)
	for {
		select {
		case <-ctx.Done():
			fmt.Println("HandelRequest Done")
			return
		default:
			fmt.Println("等一等,Handler正在執(zhí)行中")
			time.Sleep(2 * time.Second)
		}
	}
}

func WriteRedis(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("WriteRedis Done.")
			return
		default:
			fmt.Println("等一等,Redis正在執(zhí)行中")
			time.Sleep(2 * time.Second)
		}
	}
}

func WriteMysql(ctx context.Context) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println("WriteMysql Done.")
			return
		default:
			fmt.Println("等一等,Mysql正在執(zhí)行中")
			time.Sleep(2 * time.Second)
		}
	}
}

valueCtx

我們可以通過(guò)嵌套WithValue上下文,來(lái)進(jìn)行多個(gè)key-value在派生協(xié)程中傳遞,共享常量

func main() {
	ctx, cancelFunc := context.WithCancel(context.Background())
	value1 := context.WithValue(ctx, "param1", 1)
	value2 := context.WithValue(value1, "param2", 2)
	go ReadContextValue(value2)

	time.Sleep(10 * time.Second)
	cancelFunc()
	time.Sleep(5 * time.Second)
}

func ReadContextValue(ctx context.Context) {
	fmt.Println(ctx.Value("param1"))
	fmt.Println(ctx.Value("param2"))
}

到此這篇關(guān)于詳解Golang并發(fā)控制的三種方案的文章就介紹到這了,更多相關(guān)Golang并發(fā)控制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本詳解

    golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本詳解

    這篇文章主要給大家介紹了關(guān)于golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)

    Golang try catch與錯(cuò)誤處理的實(shí)現(xiàn)

    社區(qū)不少人在談?wù)?nbsp;golang 為毛不用try/catch模式,而采用苛刻的recovery、panic、defer組合,本文就來(lái)詳細(xì)的介紹一下,感興趣的可以了解一下
    2021-07-07
  • 詳解golang中的結(jié)構(gòu)體編解碼神器Mapstructure庫(kù)

    詳解golang中的結(jié)構(gòu)體編解碼神器Mapstructure庫(kù)

    mapstructure是GO字典(map[string]interface{})和Go結(jié)構(gòu)體之間轉(zhuǎn)換的編解碼工具,這篇文章主要為大家介紹一下Mapstructure庫(kù)的相關(guān)使用,希望對(duì)大家有所幫助
    2023-09-09
  • Go語(yǔ)言帶緩沖的通道實(shí)現(xiàn)

    Go語(yǔ)言帶緩沖的通道實(shí)現(xiàn)

    這篇文章主要介紹了Go語(yǔ)言帶緩沖的通道實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Go channel實(shí)現(xiàn)原理分析

    Go channel實(shí)現(xiàn)原理分析

    Channel是go語(yǔ)言?xún)?nèi)置的一個(gè)非常重要的特性,也是go并發(fā)編程的兩大基石之一,下面這篇文章主要給大家介紹了關(guān)于Go中channel的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • Go語(yǔ)言常見(jiàn)錯(cuò)誤之誤用init函數(shù)實(shí)例解析

    Go語(yǔ)言常見(jiàn)錯(cuò)誤之誤用init函數(shù)實(shí)例解析

    Go語(yǔ)言中的init函數(shù)為開(kāi)發(fā)者提供了一種在程序正式運(yùn)行前初始化包級(jí)變量的機(jī)制,然而,由于init函數(shù)的特殊性,不當(dāng)?shù)厥褂盟赡芤鹨幌盗袉?wèn)題,本文將深入探討如何有效地使用init函數(shù),列舉常見(jiàn)誤用并提供相應(yīng)的避免策略
    2024-01-01
  • Golang WaitGroup實(shí)現(xiàn)原理解析

    Golang WaitGroup實(shí)現(xiàn)原理解析

    WaitGroup是Golang并發(fā)的兩種方式之一,一個(gè)是Channel,另一個(gè)是WaitGroup,下面這篇文章主要給大家介紹了關(guān)于golang基礎(chǔ)之waitgroup用法以及使用要點(diǎn)的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • 探索Go語(yǔ)言中的switch高級(jí)用法

    探索Go語(yǔ)言中的switch高級(jí)用法

    在Go語(yǔ)言中,switch語(yǔ)句除了常見(jiàn)的用法外,還有一種不常用但有趣的寫(xiě)法,這種寫(xiě)法中,switch后面不跟任何表達(dá)式,而每個(gè)case后面跟的是返回bool類(lèi)型的函數(shù)調(diào)用表達(dá)式,這實(shí)際上是一個(gè)等價(jià)于switch true的用法,通過(guò)從上到下逐一比較case后的表達(dá)式是否為true來(lái)決定執(zhí)行哪個(gè)分支
    2024-10-10
  • Go語(yǔ)言中常量的實(shí)現(xiàn)

    Go語(yǔ)言中常量的實(shí)現(xiàn)

    Go語(yǔ)言支持單常量和多常量的定義方法,通過(guò)const關(guān)鍵字實(shí)現(xiàn),常量用于存儲(chǔ)不變的值,如圓周率或固定的錯(cuò)誤信息,旨在提高代碼的維護(hù)性和可讀性,感興趣的可以了解一下
    2024-10-10
  • Golang中的archive/zip包的常用函數(shù)詳解

    Golang中的archive/zip包的常用函數(shù)詳解

    Golang 中的 archive/zip 包用于處理 ZIP 格式的壓縮文件,提供了一系列用于創(chuàng)建、讀取和解壓縮 ZIP 格式文件的函數(shù)和類(lèi)型,下面小編就來(lái)和大家講解下常用函數(shù)吧
    2023-08-08

最新評(píng)論