Go Sync.Pool源碼閱讀

WaitGroup并發控制

sync.WaitGroup內部維護著一個計數器,計數器的值可以增加和減少。

例如當我們啟動了N 個并發任務時,就通過Add()將計數器值增加N

每個任務完成通過調用Done()方法將計數器減1

通過調用Wait()來等待并發任務執行完,當計數器值為0時,表示所有并發任務已經完成。

const N = 10

var wg = &sync.WaitGroup{}

func main() {

    for i := 0; i < N; i++ {
        //wg.Add(1) 正確寫法
        go func(i int) {
            wg.Add(1)
            println(i)
            defer wg.Done()
        }(i)
    }
    wg.Wait()

}

結果

結果不唯一,代碼存在風險, 所有go未必都能執行到

這是使用WaitGroup經常犯下的錯誤!請各位同學多次運行就會發現輸出都會不同甚至又出現報錯的問題。 這是因為go執行太快了,導致wg.Add(1)還沒有執行main函數就執行完畢了。

底層原理

type WaitGroup struct {
   noCopy noCopy

   state1 [3]uint32  // uint32數組一共12個字節,前8個即uint64記錄 高8位記錄需要等待的數量 低8位正在等待                       的數量  ,后4個字節存儲信號量,用于喚醒
}

1.核心原理就是通過之前說的64位的uint64來進行計數,采用高位記錄需要Done的數量,低位記錄Wait的數量,然后排隊休眠等待喚醒

2.如果發現當前count>0則 Wait的goroutine會進行排隊

3.任務完成后的goroutine則進行Done操作,直到count==0,則完成,就喚醒所有因為wait操作睡眠的goroutine

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 問題 當main goroutine為了等待work goroutine都運行完畢,不得不在程序末尾使用time....
    JunChow520閱讀 449評論 0 0
  • sync.WaitGroup sync.WaitGroup類型(以下簡稱WaitGroup類型)是開箱即用的,也是...
    尼桑麻閱讀 1,008評論 0 0
  • 本文從上下文Context、同步原語與鎖、Channel、調度器四個方面介紹Go語言是如何實現并發的。本文絕大部分...
    彥幀閱讀 1,599評論 1 3
  • Go語言中的并發編程 并發是編程里面一個非常重要的概念,Go語言在語言層面天生支持并發,這也是Go語言流行的一個很...
    吳佳浩閱讀 371評論 0 1
  • 1 前言 WaitGroup是Golang應用開發過程中經常使用的并發控制技術。WaitGroup,可理解為Wai...
    杰克慢閱讀 915評論 0 1