最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go語言并發(fā)之WaitGroup的用法詳解

 更新時間:2023年06月09日 09:17:27   作者:zsx_yiyiyi  
這篇文章主要詳細介紹了Go語言并發(fā)中得到WaitGroup,文中有相關(guān)的代碼示例供大家參考,對我們的學(xué)習(xí)或工作有一定的參考價值,感興趣的同學(xué)跟著小編一起來學(xué)習(xí)吧

1、Go語言并發(fā)之WaitGroup

goroutine 和 chan,一個用于并發(fā),另一個用于通信。沒有緩沖的通道具有同步的功能,除此之外,sync 包也提

供了多個 goroutine 同步的機制,主要是通過 WaitGroup 實現(xiàn)的。

WaitGroup 用來等待多個 goroutine 完成,main goroutine 調(diào)用 Add 設(shè)置需要等待 goroutine 的數(shù)目,每一個

goroutine 結(jié)束時調(diào)用 Done(),Wait() 被 main 用來等待所有的 goroutine 完成。

主要數(shù)據(jù)結(jié)構(gòu)和操作如下:

type WaitGroup struct {
	// contains filtered or unexported fields
}
// 添加等待信號
func (wg*WaitGroup) Add (delta int)
// 釋放等待信號
func (wg*WaitGroup) Done()
// 等待
func (wg*WaitGroup) Wait()

下面的程序演示如何使用 sync.WaitGroup 完成多個 goroutine 之間的協(xié)同工作。

package main
import (
	"net/http"
	"sync"
)
var wg sync.WaitGroup
var urls = []string{
	"https://news.sina.com.cn/",
	"https://www.bilibili.com/",
	"https://www.qq.com/",
}
func main() {
	for _, url := range urls {
		//每一個url啟動一個goroutine,同時給wg加1
		wg.Add(1)
		// 啟動一個goroutine獲取URL
		go func(url string) {
			// 當(dāng)前goroutine結(jié)束后給wg計數(shù)減1 ,wg.Done()等價于wg.Add(-1)
			// defer wg.Add(-1)
			defer wg.Done()
			// 發(fā)送http get請求并打印http返回碼
			resp, err := http.Get(url)
			if err == nil {
				println(resp.Status)
			}
		}(url)
	}
	// 等待所有HTTP獲取完成
	wg.Wait()
}

# 輸出
501 Not Implemented
200 OK
200 OK

1.1 不加鎖

多線程中使用睡眠函數(shù)不優(yōu)雅,直接用 sync.WaitGroup 保證一個 goroutine 剛退出就可以繼續(xù)執(zhí)行,不需要自

己猜需要 sleep 多久。

package main
import (
	"fmt"
	"sync"
)
var wg sync.WaitGroup
func main() {
	// 啟動一個goroutine就登記+1,啟動十個就+10
	wg.Add(10)
	var count = 0
	for i := 0; i < 10; i++ {
		go func() {
			// goroutine結(jié)束就登記-1
			defer wg.Done()
			for j := 0; j < 100000; j++ {
				count++
			}
		}()
	}
	// 等待所有登記的goroutine都結(jié)束
	wg.Wait()
	// 346730
	fmt.Print(count)
}

啟動十個goroutine對count自增10w次,理想狀況為100w,但由于沒有鎖,會出現(xiàn)實際情況遠遠小于并且不相等

的情況。為什么會出現(xiàn)這樣的結(jié)果?因為自增并不是一個原子操作,很可能幾個goroutine同時讀到同一個數(shù),自

增,又將同樣的數(shù)寫了回去。

1.2 互斥鎖

1.2.1 直接使用鎖

共享資源是count變量,臨界區(qū)是count++,臨界區(qū)之前加鎖,使其他goroutine在臨界區(qū)阻塞,離開臨界區(qū)解

鎖,就可以解決這個 data race 的問題。go語言是通過 sync.Mutex 實現(xiàn)這一功能。

package main
import (
	"fmt"
	"sync"
)
var wg sync.WaitGroup
func main() {
	// 定義鎖
	var mu sync.Mutex
	wg.Add(10)
	var count = 0
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < 100000; j++ {
				// 加鎖
				mu.Lock()
				count++
				// 解鎖
				mu.Unlock()
			}
		}()
	}
	wg.Wait()
	// 1000000
	fmt.Print(count)
}

1.2.2 嵌入字段方式使用鎖

把 Mutex 嵌入 struct,可以直接在這個 struct 上使用 Lock/Unlock。

package main
import (
	"fmt"
	"sync"
)
var wg sync.WaitGroup
type Counter struct {
	sync.Mutex
	Count uint64
}
func main() {
	var counter Counter
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func() {
			defer wg.Done()
			for j := 0; j < 100000; j++ {
				counter.Lock()
				counter.Count++
				counter.Unlock()
			}
		}()
	}
	wg.Wait()
	// 1000000
	fmt.Print(counter.Count)
}

1.2.3 把加/解鎖封裝成方法

package main
import (
	"fmt"
	"sync"
)
var wg sync.WaitGroup
type Counter struct {
	mu    sync.Mutex
	count uint64
}
func (c *Counter) Incr() {
	c.mu.Lock()
	c.count++
	c.mu.Unlock()
}
func (c *Counter) Count() uint64 {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.count
}
func main() {
	var counter Counter
	// 啟動一個goroutine就登記+1,啟動十個就+10
	wg.Add(10)
	for i := 0; i < 10; i++ {
		go func() {
			// goroutine結(jié)束就登記-1
			defer wg.Done()
			for j := 0; j < 100000; j++ {
				counter.Incr()
			}
		}()
	}
	// 等待所有登記的goroutine都結(jié)束
	wg.Wait()
	// 1000000
	fmt.Print(counter.Count())
}

到此這篇關(guān)于Go語言并發(fā)之WaitGroup的用法詳解的文章就介紹到這了,更多相關(guān)Go語言 WaitGroup內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go語言調(diào)用其他包中的函數(shù)簡單示例

    go語言調(diào)用其他包中的函數(shù)簡單示例

    這篇文章主要給大家介紹了關(guān)于go語言調(diào)用其他包中的函數(shù)的相關(guān)資料,文中還介紹了Go語言同一個包中不同文件之間函數(shù)調(diào)用的相關(guān)問題,需要的朋友可以參考下
    2023-01-01
  • 如何讓shell終端和goland控制臺輸出彩色的文字

    如何讓shell終端和goland控制臺輸出彩色的文字

    這篇文章主要介紹了如何讓shell終端和goland控制臺輸出彩色的文字的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • Go信號處理如何優(yōu)雅地關(guān)閉你的應(yīng)用

    Go信號處理如何優(yōu)雅地關(guān)閉你的應(yīng)用

    Go?中的優(yōu)雅關(guān)閉機制使得在應(yīng)用程序接收到終止信號時,能夠進行平滑的資源清理,通過使用?context?來管理?goroutine?的生命周期,結(jié)合?signal?包捕獲系統(tǒng)信號,你可以在?Go?應(yīng)用中實現(xiàn)一個健壯且優(yōu)雅的關(guān)閉過程,對Go關(guān)閉應(yīng)用相關(guān)操作感興趣的朋友一起看看吧
    2025-01-01
  • Go語言內(nèi)建函數(shù)cap的實現(xiàn)示例

    Go語言內(nèi)建函數(shù)cap的實現(xiàn)示例

    cap 是一個常用的內(nèi)建函數(shù),它用于獲取某些數(shù)據(jù)結(jié)構(gòu)的容量,本文主要介紹了Go語言內(nèi)建函數(shù)cap的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • Go中的Timer 和 Ticker詳解

    Go中的Timer 和 Ticker詳解

    在日常開發(fā)中,我們可能會遇到需要延遲執(zhí)行或周期性地執(zhí)行一些任務(wù),這個時候就需要用到 Go 語言中的定時器,本文將會對這兩種定時器類型進行介紹,感興趣的朋友一起看看吧
    2024-07-07
  • Go語言中的HTTP客戶端從標(biāo)準(zhǔn)庫到第三方庫

    Go語言中的HTTP客戶端從標(biāo)準(zhǔn)庫到第三方庫

    本文介紹了Go語言中的HTTP客戶端開發(fā),涵蓋標(biāo)準(zhǔn)庫和第三方庫使用、最佳實踐、高級功能、HTTP/2支持、安全考慮、性能優(yōu)化等內(nèi)容,通過本文,讀者可以構(gòu)建高效、可靠的HTTP客戶端應(yīng)用
    2026-05-05
  • Golang中defer與recover的組合使用示例代碼

    Golang中defer與recover的組合使用示例代碼

    Go語言的defer和recover機制為開發(fā)者提供了一種優(yōu)雅處理錯誤的方式,幫助保持程序的穩(wěn)定性和可維護性,這篇文章主要介紹了Golang中defer與recover組合使用的相關(guān)資料,需要的朋友可以參考下
    2025-06-06
  • 在Go中格式化字符串的幾種常用方法

    在Go中格式化字符串的幾種常用方法

    Go對字符串格式化提供了良好的支持,這篇文章主要給大家介紹了關(guān)于在Go中格式化字符串的幾種常用方法,文中通過代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用Go具有一定的參考價值,需要的朋友可以參考下
    2023-10-10
  • golang多次讀取http request body的問題分析

    golang多次讀取http request body的問題分析

    這篇文章主要給大家分析了golang多次讀取http request body的問題,文中通過代碼示例和圖文介紹的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • Go語言遍歷循環(huán)的幾種方法

    Go語言遍歷循環(huán)的幾種方法

    遍歷循環(huán)主要用于迭代數(shù)組、切片、映射(map)、字符串等數(shù)據(jù)結(jié)構(gòu),本文主要介紹了Go語言遍歷循環(huán)的幾種方法,下面就來介紹一下,具有一定的參考價值,感興趣的可以了解一下
    2025-03-03

最新評論

古交市| 左权县| 紫金县| 虎林市| 奉贤区| 阜城县| 穆棱市| 江山市| 视频| 丰都县| 枣强县| 七台河市| 扎兰屯市| 黎城县| 庐江县| 沐川县| 全州县| 临颍县| 哈巴河县| 项城市| 黔东| 永吉县| 读书| 齐河县| 会东县| 娱乐| 黔南| 湄潭县| 花莲县| 乡城县| 施秉县| 绿春县| 罗源县| 铜梁县| 盐山县| 晋城| 永登县| 清原| 新丰县| 普定县| 乌审旗|