日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
一篇學(xué)會(huì)Go并發(fā)等待

上節(jié)答疑

上一節(jié)有讀者問goroutine stack size一般是多大,我進(jìn)行了詳細(xì)的查詢

創(chuàng)新互聯(lián)建站是專業(yè)的阿拉山口網(wǎng)站建設(shè)公司,阿拉山口接單;提供網(wǎng)站設(shè)計(jì)、做網(wǎng)站,網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行阿拉山口網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

關(guān)于 goroutine stack size(棧內(nèi)存大小) 官方的文檔 中所述,1.2 之前最小是4kb,在1.2 變成8kb,并且可以使用SetMaxStack 設(shè)置棧最大大小。

在 runtime/debug 包能控制最大的單個(gè) goroutine 的堆棧的大小。在 64 位系統(tǒng)上默認(rèn)為 1GB,在 32 位系統(tǒng)上默認(rèn)為 250MB。

因?yàn)槊總€(gè)goroutine需要能夠運(yùn)行,所以它們都有自己的棧。假如每個(gè)goroutine分配固定棧大小并且不能增長,太小則會(huì)導(dǎo)致溢出,太大又會(huì)浪費(fèi)空間,無法存在許多的goroutine。

所以在1.3版本中,改為了 Contiguous stack( 連續(xù)棧 ),為了解決這個(gè)問題,goroutine可以初始時(shí)只給棧分配很小的空間(8KB),然后隨著使用過程中的需要自動(dòng)地增長。這就是為什么Go可以開千千萬萬個(gè)goroutine而不會(huì)耗盡內(nèi)存。

1.4 版本 goroutine 堆棧從 8Kb 減少到 2Kb

Golang并發(fā)等待

本節(jié)源碼位置 https://github.com/golang-minibear2333/golang/blob/master/4.concurrent/goroutine-wait/”

簡介

goroutine 是 Golang 中非常有用的功能,有時(shí)候 goroutine 沒執(zhí)行完函數(shù)就返回了,如果希望等待當(dāng)前的 goroutine 執(zhí)行完成再接著往下執(zhí)行,該怎么辦?

 
 
 
  1. func say(s string) { 
  2.     for i := 0; i < 3; i++ { 
  3.         time.Sleep(100 * time.Millisecond) 
  4.         fmt.Println(s) 
  5.     } 
  6.  
  7. func main() { 
  8.     go say("hello world") 
  9.     fmt.Println("over!") 

輸出 over! , 主線程沒有等待

使用 Sleep 等待

 
 
 
  1. func main() { 
  2.     go say("hello world") 
  3.     time.Sleep(time.Second*1) 
  4.     fmt.Println("over!") 

運(yùn)行修改后的程序,結(jié)果如下:

 
 
 
  1. hello world 
  2. hello world 
  3. hello world 
  4. over! 

結(jié)果符合預(yù)期,但是太 low 了,我們不知道實(shí)際執(zhí)行中應(yīng)該等待多長時(shí)間,所以不能接受這個(gè)方案!

發(fā)送信號(hào)

 
 
 
  1. func main() { 
  2.     done := make(chan bool) 
  3.     go func() { 
  4.         for i := 0; i < 3; i++ { 
  5.             time.Sleep(100 * time.Millisecond) 
  6.             fmt.Println("hello world") 
  7.         } 
  8.         done <- true 
  9.     }() 
  10.  
  11.     <-done 
  12.     fmt.Println("over!") 

輸出的結(jié)果和上面相同,也符合預(yù)期

這種方式不能處理多個(gè)協(xié)程,所以也不是優(yōu)雅的解決方式。

WaitGroup

Golang 官方在 sync 包中提供了 WaitGroup 類型可以解決這個(gè)問題。其文檔描述如下:

使用方法可以總結(jié)為下面幾點(diǎn):

  • 在父協(xié)程中創(chuàng)建一個(gè) WaitGroup 實(shí)例,比如名稱為:wg
  • 調(diào)用 wg.Add(n) ,其中 n 是等待的 goroutine 的數(shù)量
  • 在每個(gè) goroutine 運(yùn)行的函數(shù)中執(zhí)行 defer wg.Done()
  • 調(diào)用 wg.Wait() 阻塞主邏輯
  • 直到所有 goroutine 執(zhí)行完成。
 
 
 
  1. func main() { 
  2.     var wg sync.WaitGroup 
  3.     wg.Add(2) 
  4.     go say2("hello", &wg) 
  5.     go say2("world", &wg) 
  6.     fmt.Println("over!") 
  7.     wg.Wait() 
  8.  
  9. func say2(s string, waitGroup *sync.WaitGroup) { 
  10.     defer waitGroup.Done() 
  11.  
  12.     for i := 0; i < 3; i++ { 
  13.         fmt.Println(s) 
  14.     } 

輸出,注意順序混亂是因?yàn)椴l(fā)執(zhí)行

 
 
 
  1. hello 
  2. hello 
  3. hello 
  4. over! 
  5. world 
  6. world 
  7. world 

小心缺陷

簡短的例子,注意循環(huán)傳入的變量用中間變量替代,防止閉包 bug

 
 
 
  1. func errFunc() { 
  2.  var wg sync.WaitGroup 
  3.  sList := []string{"a", "b"} 
  4.  wg.Add(len(sList)) 
  5.  for _, d := range sList { 
  6.   go func() { 
  7.    defer wg.Done() 
  8.    fmt.Println(d) 
  9.   }() 
  10.  } 
  11.  wg.Wait() 

輸出,可以發(fā)現(xiàn)全部變成了最后一個(gè)

 
 
 

父協(xié)程與子協(xié)程是并發(fā)的。父協(xié)程上的for循環(huán)瞬間執(zhí)行完了,內(nèi)部的協(xié)程使用的是d最后的值,這就是閉包問題。

解決方法當(dāng)作參數(shù)傳入

 
 
 
  1. func correctFunc() { 
  2.  var wg sync.WaitGroup 
  3.  sList := []string{"a", "b"} 
  4.  wg.Add(len(sList)) 
  5.  for _, d := range sList { 
  6.   go func(str string) { 
  7.    defer wg.Done() 
  8.    fmt.Println(str) 
  9.   }(d) 
  10.  } 
  11.  wg.Wait() 

輸出

 
 
 

要留意 range 中的value有可能出現(xiàn) 1.7.3 有可能會(huì)遇到的坑!


文章名稱:一篇學(xué)會(huì)Go并發(fā)等待
文章URL:http://www.dlmjj.cn/article/dhieopd.html