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

解決golang sync.Wait()不執(zhí)行的問題

 更新時(shí)間:2020年12月23日 10:57:34   作者:Tangs_  
這篇文章主要介紹了解決golang sync.Wait()不執(zhí)行的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧

goroutine 似乎不用解釋太多,可以利用它實(shí)現(xiàn)多線程,也可以利用它來實(shí)現(xiàn)異步事件。

在使用關(guān)鍵字go的過程中,常常會(huì)將用到sync.WaitGroup,如下一段代碼。

package main
import (
	"fmt"
	"sync"
	"time"
)
func Run() {
	var wg = &sync.WaitGroup{}
	go func() {
		wg.Add(1)
		fmt.Println("halo world start")
		time.Sleep(time.Second * 5)
		fmt.Println("halo world end")
		wg.Done()
	}()
	// time.Sleep(time.Millisecond * 5)
	// fmt.Println("server will start")
	wg.Wait()
}
func main() {
	Run()
}
// output:
// 

期待的結(jié)果是打印 halo world start,5秒后打印halo world end,但是結(jié)果就是什么都沒有,并且進(jìn)程立即就結(jié)束了。

原因

關(guān)鍵字go是異步的,當(dāng)執(zhí)行到go,不會(huì)立即執(zhí)行g(shù)o 后面的內(nèi)容,而且繼續(xù)往下執(zhí)行。此時(shí)wg.Add(1)還沒有來得及執(zhí)行,wg.Wait()就已經(jīng)執(zhí)行,即不會(huì)發(fā)生等待,進(jìn)程就結(jié)束了。

怎么解決:

只需要在wg.Wait()前有其他操作,給與足夠的時(shí)間讓wg.Add(1)執(zhí)行即可,

方法一、時(shí)間等待,在wg.Wait()前加一句time.Sleep(time.Millisecond*5),既不影響性能,也能讓wg.Add(1)來得及執(zhí)行

方法二、有IO操作,在wg.Wait()有其他IO操作,比如fmt.Println("server will start"),原因是std的輸出會(huì)將進(jìn)程從用戶態(tài)轉(zhuǎn)向內(nèi)核態(tài),打印命令發(fā)出后,又切回用戶態(tài),這個(gè)狀態(tài)的轉(zhuǎn)換是很有消耗的,wg.Add(1)也就有時(shí)間執(zhí)行。

Don't worry

是否有存在擔(dān)心,方法一的時(shí)間等待,等待的時(shí)候不夠長,還是讓wg.Add(1)來不及執(zhí)行。don't worry.

這里涉及到goroutine的調(diào)度問題,go進(jìn)程在執(zhí)行過程中,必須從goroutine隊(duì)列中取出一個(gè)來執(zhí)行,當(dāng)wg.Wait()執(zhí)行前就算執(zhí)行time.Sleep(time.Nanosecond), 一納秒,一…一…一納秒,wg.Add(1)也來得及執(zhí)行,因?yàn)橹鱣oroutine會(huì)被切換到睡眠狀態(tài),go進(jìn)程必須要取一個(gè)線程來執(zhí)行,就會(huì)取到wg.Add(1)這個(gè)線程,接下來就順理成章了。

同時(shí)方法二也是異曲同工,當(dāng)發(fā)出打印的事件,整個(gè)進(jìn)程都會(huì)被切換到就緒態(tài),然后再被cpu執(zhí)行。

補(bǔ)充:【golang】sync.WaitGroup{}的wait()調(diào)用位置不同導(dǎo)致意想不到錯(cuò)誤

協(xié)程go多了,總覺的天下我有,沒事就喜歡go一個(gè)協(xié)程,信手拈來,在項(xiàng)目中寫個(gè)如下類似代碼:

  wh := sync.WaitGroup{}
  out := make(chan string)
  go func() {
    wh.Wait()
    close(out)
  }()
  go func() {
    for i := 0; i < 2; i++ {
      wh.Add(1)
      go tt(out)
      wh.Done()
    }
  }()

想著開個(gè)協(xié)程去wait所有協(xié)程組,測(cè)試一下通了,沒問題,好牛逼,協(xié)程呀??!

可多測(cè)試即便就會(huì)出現(xiàn):

send close channel

或者協(xié)程定死在某一個(gè),還自已為是的認(rèn)為自己寫的子方法估計(jì)不小心關(guān)閉了channel,找了半天只找到在wg.wait()后進(jìn)行了關(guān)閉。就這樣扣了好久,還沒想到自己畫蛇添足的錯(cuò)誤,經(jīng)大佬一指點(diǎn),原來開一個(gè)協(xié)程,還沒等后一個(gè)協(xié)程進(jìn)行wg.add(1)操作,wg.wait()就已經(jīng)過了,關(guān)閉了channel。

只好老老實(shí)實(shí)寫:

  wh := sync.WaitGroup{}
  out := make(chan string)
  go func() {
    for i := 0; i < 2; i++ {
      wh.Add(1)
      go tt(out)
      wh.Done()
    }
    wh.Wait()
    close(out)
  }()

其實(shí)就是一個(gè)小小的同步問題,旁觀者清呀?。?!

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • Golang小數(shù)操作指南之判斷小數(shù)點(diǎn)位數(shù)與四舍五入

    Golang小數(shù)操作指南之判斷小數(shù)點(diǎn)位數(shù)與四舍五入

    這篇文章主要給大家介紹了關(guān)于Golang小數(shù)操作指南之判斷小數(shù)點(diǎn)位數(shù)與四舍五入的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-03-03
  • Go語言擴(kuò)展原語之ErrGroup的用法詳解

    Go語言擴(kuò)展原語之ErrGroup的用法詳解

    除標(biāo)準(zhǔn)庫中提供的同步原語外,Go語言還在子倉庫sync中提供了4種擴(kuò)展原語,本文主要為大家介紹的是其中的golang/sync/errgroup.Group,感興趣的小伙伴可以了解一下
    2023-07-07
  • 使用Go語言實(shí)現(xiàn)配置文件熱加載功能

    使用Go語言實(shí)現(xiàn)配置文件熱加載功能

    這篇文章主要介紹了使用Go語言實(shí)現(xiàn)配置文件熱加載功能,以及配置文件熱加載包的實(shí)現(xiàn)思路,需要的朋友可以參考下
    2018-03-03
  • GoLang協(xié)程庫libtask學(xué)習(xí)筆記

    GoLang協(xié)程庫libtask學(xué)習(xí)筆記

    libtask一個(gè)C語言的協(xié)程庫,是go語言的前身很早期的原型. 測(cè)試機(jī)器是我的mac air 安裝的centos虛擬機(jī)(只有一個(gè)核), 代碼沒有采用任何優(yōu)化,只是使用默認(rèn)配置
    2022-12-12
  • go語言中decimal的用法詳解

    go語言中decimal的用法詳解

    本文主要介紹了go語言中decimal的用法詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • Go通過不變性優(yōu)化程序詳解

    Go通過不變性優(yōu)化程序詳解

    這篇文章主要為大家介紹了Go通過不變性優(yōu)化程序?qū)嵗斀猓行枰呐笥芽梢越梃b參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • Go設(shè)計(jì)模式之中介者模式講解和代碼示例

    Go設(shè)計(jì)模式之中介者模式講解和代碼示例

    中介者是一種行為設(shè)計(jì)模式,讓程序組件通過特殊的中介者對(duì)象進(jìn)行間接溝通,達(dá)到減少組件之間依賴關(guān)系的目的,因此本文就給大家詳細(xì)介紹一下Go中介者模式,需要的朋友可以參考下
    2023-06-06
  • Go實(shí)現(xiàn)set類型的示例代碼

    Go實(shí)現(xiàn)set類型的示例代碼

    本文主要介紹了Go實(shí)現(xiàn)set類型的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Golang flag包的具體使用

    Golang flag包的具體使用

    本文主要介紹了Golang flag包的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • Go?channel結(jié)構(gòu)體源碼和讀寫和關(guān)閉過程詳解

    Go?channel結(jié)構(gòu)體源碼和讀寫和關(guān)閉過程詳解

    這篇文章主要介紹了Go?channel結(jié)構(gòu)體源碼和讀寫和關(guān)閉過程,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05

最新評(píng)論