1. 程式人生 > 其它 >Golang WaitGroup原始碼解析

Golang WaitGroup原始碼解析

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)

  1. 更新counter的值。counter += n
  2. 判斷當前counter > 0 || waiter == 0
    ,滿足條件,說明當前還有groutine沒有執行完,直接返回。
  3. 走到這一步,說明counter == 0 && waiter != 0,說明groutine全部執行了Done()方法,換醒執行了wg.Wait()的協程,將state設定成0,返回。

Wait()

  1. 迴圈判斷下面操作
  2. 判斷counter == 0,如果為true,說明groutine已經全部執行了Done()方法,Wait Done。
  3. 此時counter != 0,說明需要阻塞當前協程的執行,執行下面的CAS判斷
  4. CAS判斷wg.state有沒有被改變,沒有則更新wg.state為1,當前協程進入sleep狀態,等待訊號量換醒。換醒後繼續迴圈判斷,此時counter==0,直接wait done。
  5. CAS判斷wg.state有沒有被改變,則繼續迴圈判斷。繼續判斷counter

Done()

Done 的實現就是 Add. 只不過我們常規用法 wg.Add(1) 是加 1 ,wg.Done() 是減 1,即 wg.Done() 可以用 wg.Add(-1) 來代替。儘管我們知道 wg.Add 可以傳遞負數當 wg.Done 使用,但是還是別這麼用。