C語言中文網 目錄
首頁 > Go語言教程 > Go語言并發 閱讀:1,920

Go語言等待組(sync.WaitGroup)

除了可以使用通道(channel)和互斥鎖進行兩個并發程序間的同步外,還可以使用等待組進行多個任務的同步,等待組可以保證在并發環境中完成指定數量的任務

等待組有下面幾個方法可用,如下表所示。

等待組的方法
方法名 功能
(wg * WaitGroup) Add(delta int) 等待組的計數器 +1
(wg *WaitGroup) Done() 等待組的計數器 -1
(wg *WaitGroup) Wait() 當等待組計數器不等于 0 時阻塞直到變 0。

等待組內部擁有一個計數器,計數器的值可以通過方法調用實現計數器的增加和減少。當我們添加了 N 個并發任務進行工作時,就將等待組的計數器值增加 N。每個任務完成時,這個值減 1。同時,在另外一個 goroutine 中等待這個等待組的計數器值為 0 時,表示所有任務已經完成。

下面的代碼演示了這一過程:
package main

import (
    "fmt"
    "net/http"
    "sync"
)

func main() {

    // 聲明一個等待組
    var wg sync.WaitGroup

    // 準備一系列的網站地址
    var urls = []string{
        "http://www.github.com/",
        "https://www.qiniu.com/",
        "https://www.golangtc.com/",
    }

    // 遍歷這些地址
    for _, url := range urls {

        // 每一個任務開始時, 將等待組增加1
        wg.Add(1)

        // 開啟一個并發
        go func(url string) {

            // 使用defer, 表示函數完成時將等待組值減1
            defer wg.Done()

            // 使用http訪問提供的地址
            _, err := http.Get(url)

            // 訪問完成后, 打印地址和可能發生的錯誤
            fmt.Println(url, err)

            // 通過參數傳遞url地址
        }(url)
    }

    // 等待所有的任務完成
    wg.Wait()

    fmt.Println("over")
}
代碼說明如下:
  • 第 12 行,聲明一個等待組,對一組等待任務只需要一個等待組,而不需要每一個任務都使用一個等待組。
  • 第 15 行,準備一系列可訪問的網站地址的字符串切片。
  • 第 22 行,遍歷這些字符串切片。
  • 第 25 行,將等待組的計數器加1,也就是每一個任務加 1。
  • 第 28 行,將一個匿名函數開啟并發。
  • 第 31 行,在匿名函數結束時會執行這一句以表示任務完成。wg.Done() 方法等效于執行 wg.Add(-1)。
  • 第 34 行,使用 http 包提供的 Get() 函數對 url 進行訪問,Get() 函數會一直阻塞直到網站響應或者超時。
  • 第 37 行,在網站響應和超時后,打印這個網站的地址和可能發生的錯誤。
  • 第 40 行,這里將 url 通過 goroutine 的參數進行傳遞,是為了避免 url 變量通過閉包放入匿名函數后又被修改的問題。
  • 第 44 行,等待所有的網站都響應或者超時后,任務完成,Wait 就會停止阻塞。

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo