Golang WaitGroup原始碼解析
阿新 • • 發佈:2022-04-13
Go WaitGroup原始碼解析
結構體
type WaitGroup struct {
noCopy noCopy
state1 [3]uint32
}
其中state1代表三個欄位:counter, waiter, sema
- counter:計數器,每次經過wg.Add(X)或者wg.Done()後的值
- waiter:呼叫wg.Wait()的數量,也就是等待者的數量
- sema:訊號量,用於換醒Wait()函式
退出WaitGroup的條件
counter == 0
Add(n)
- 更新counter的值。
counter += n
- 判斷當前
counter > 0 || waiter == 0
- 走到這一步,說明
counter == 0 && waiter != 0
,說明groutine全部執行了Done()方法,換醒執行了wg.Wait()的協程,將state設定成0,返回。
Wait()
- 迴圈判斷下面操作
- 判斷
counter == 0
,如果為true,說明groutine已經全部執行了Done()方法,Wait Done。 - 此時
counter != 0
,說明需要阻塞當前協程的執行,執行下面的CAS判斷 - CAS判斷wg.state有沒有被改變,沒有則更新wg.state為1,當前協程進入sleep狀態,等待訊號量換醒。換醒後繼續迴圈判斷,此時counter==0,直接wait done。
- CAS判斷wg.state有沒有被改變,有則繼續迴圈判斷。繼續判斷counter
Done()
Done 的實現就是 Add. 只不過我們常規用法 wg.Add(1) 是加 1 ,wg.Done() 是減 1,即 wg.Done() 可以用 wg.Add(-1) 來代替。儘管我們知道 wg.Add 可以傳遞負數當 wg.Done 使用,但是還是別這麼用。