中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

sync.Wait()函數無法在golang中執行如何解決

發布時間:2020-12-23 13:58:55 來源:億速云 閱讀:198 作者:Leah 欄目:開發技術

sync.Wait()函數無法在golang中執行如何解決?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

goroutine 似乎不用解釋太多,可以利用它實現多線程,也可以利用它來實現異步事件。

在使用關鍵字go的過程中,常常會將用到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:
//

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

原因

關鍵字go是異步的,當執行到go,不會立即執行go 后面的內容,而且繼續往下執行。此時wg.Add(1)還沒有來得及執行,wg.Wait()就已經執行,即不會發生等待,進程就結束了。

怎么解決:

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

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

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

Don't worry

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

這里涉及到goroutine的調度問題,go進程在執行過程中,必須從goroutine隊列中取出一個來執行,當wg.Wait()執行前就算執行time.Sleep(time.Nanosecond), 一納秒,一…一…一納秒,wg.Add(1)也來得及執行,因為主goroutine會被切換到睡眠狀態,go進程必須要取一個線程來執行,就會取到wg.Add(1)這個線程,接下來就順理成章了。

同時方法二也是異曲同工,當發出打印的事件,整個進程都會被切換到就緒態,然后再被cpu執行。

補充:【golang】sync.WaitGroup{}的wait()調用位置不同導致意想不到錯誤

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

  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()
    }
  }()

想著開個協程去wait所有協程組,測試一下通了,沒問題,好牛逼,協程呀!!

可多測試即便就會出現:

send close channel

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

只好老老實實寫:

  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)
  }()

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

海丰县| 札达县| 漳浦县| 麻江县| 庆阳市| 临桂县| 宁津县| 岫岩| 桃江县| 郯城县| 综艺| 垫江县| 宣化县| 清新县| 科尔| 庆安县| 洱源县| 肥乡县| 万载县| 梁平县| 葵青区| 宁晋县| 门头沟区| 海伦市| 永和县| 义乌市| 营口市| 定南县| 和林格尔县| 石台县| 巴彦淖尔市| 定远县| 本溪| 岳阳县| 锡林浩特市| 郎溪县| 台北市| 乐安县| 都兰县| 大石桥市| 砚山县|