Go語言等待組(sync.WaitGroup)

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

    在sync.WaitGroup(等待組)類型中,每個sync.WaitGroup值在內部維護着一個計數,此計數的初始默認值爲零。

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

                    

 

對於一個可尋址的sync.WaitGroup值wg:

1、我們可以使用方法調用wg.Add(delta)來改變值 wg 維護的計數。

2、方法調用 wg.Done() 和 wg.Add(-1) 是完全等價的。

3、如果一個 wg.Add(delta) 或者 wg.Done() 調用將 wg 維護的計數更改成一個負數,一個恐慌將產生。

  • 當一個協程調用了 wg.Wait() 時,
  • 如果此時 wg 維護的計數爲零,則此 wg.Wait() 此操作爲一個空操作(noop);
  •  否則(計數爲一個正整數),此協程將進入阻塞狀態。當以後其它某個協程將此計數更改至 0 時(一般通過調用 wg.Done()),此協程將重新進入運行狀態(即 wg.Wait() 將返回)。

等待組內部擁有一個計數器,計數器的值可以通過方法調用實現計數器的增加和減少。當我們添加了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")

}

輸出:

http://www.github.com/ Get http://www.github.com/: read tcp 192.168.2.129:55170->13.229.188.59:80: wsarecv: An existing connection was forcibly closed by the remote host.

https://www.qiniu.com/ <nil>

https://www.golangtc.com/ <nil>

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 就會停止阻塞。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章