国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Go語言并發(fā)之WaitGroup

這篇具有很好參考價值的文章主要介紹了Go語言并發(fā)之WaitGroup。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

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) {
			// 當前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。文章來源地址http://www.zghlxwxcb.cn/news/detail-476077.html

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的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • 7 文件操作、單元測試、goroutine【Go語言教程】

    7 文件操作、單元測試、goroutine【Go語言教程】

    1.1 介紹 os.File 封裝所有文件相關(guān)操作,F(xiàn)ile 是一個結(jié)構(gòu)體 常用方法: 打開文件 關(guān)閉文件 1.2 應用實例 ①讀文件 常用方法: ①bufio.NewReader(), reader.ReadString【帶緩沖】 ②io/ioutil【一次性讀取,適用于小文件】 讀取文件的內(nèi)容并顯示在終端(帶緩沖區(qū)的方式),使用 os.Open, file.

    2024年02月04日
    瀏覽(24)
  • Go語言入門記錄:從基礎(chǔ)到變量、函數(shù)、控制語句、包引用、interface、panic、go協(xié)程、Channel、sync下的waitGroup和Once等

    Go語言入門記錄:從基礎(chǔ)到變量、函數(shù)、控制語句、包引用、interface、panic、go協(xié)程、Channel、sync下的waitGroup和Once等

    程序入口文件的包名必須是main,但主程序文件所在文件夾名稱不必須是 main ,即我們下圖 hello_world.go 在 main 中,所以感覺 package main 寫順理成章,但是如果我們把 main 目錄名稱改成隨便的名字如 filename 也是可以運行的,所以迷思就在于寫在文件開頭的那個 package main 和 java

    2024年02月11日
    瀏覽(19)
  • Golang之路---04 并發(fā)編程——WaitGroup

    Golang之路---04 并發(fā)編程——WaitGroup

    為了保證 main goroutine 在所有的 goroutine 都執(zhí)行完畢后再退出,前面使用了 time.Sleep 這種簡單的方式。 由于寫的 demo 都是比較簡單的, sleep 個 1 秒,我們主觀上認為是夠用的。 但在實際開發(fā)中,開發(fā)人員是無法預知,所有的 goroutine 需要多長的時間才能執(zhí)行完畢,sleep 多了,

    2024年02月14日
    瀏覽(25)
  • 深入理解 go sync.Waitgroup

    深入理解 go sync.Waitgroup

    本文基于 Go 1.19。 go 里面的 WaitGroup 是非常常見的一種并發(fā)控制方式,它可以讓我們的代碼等待一組 goroutine 的結(jié)束。 比如在主協(xié)程中等待幾個子協(xié)程去做一些耗時的操作,如發(fā)起幾個 HTTP 請求,然后等待它們的結(jié)果。 下面的代碼展示了一個 goroutine 等待另外 2 個 goroutine 結(jié)束

    2024年01月16日
    瀏覽(16)
  • 控制goroutine 的并發(fā)執(zhí)行數(shù)量

    控制goroutine 的并發(fā)執(zhí)行數(shù)量

    正常項目,協(xié)程數(shù)量超過十萬就需要引起重視。如果有上百萬goroutine,一般是有問題的。 但并不是說協(xié)程數(shù)量的上限是100多w 1048575的來自類似如下的demo代碼: 執(zhí)行后,很快報錯 panic: too many concurrent operations on a single file or socket (max 1048575) 但這個是因為fmt.Printf導致的: 對單個

    2024年02月11日
    瀏覽(15)
  • 掌握Go并發(fā):Go語言并發(fā)編程深度解析

    掌握Go并發(fā):Go語言并發(fā)編程深度解析

    ??? 個人主頁 :鼠鼠我捏,要死了捏的主頁? ??? 系列專欄 :Golang全棧-專欄 ??? 個人學習筆記,若有缺誤,歡迎評論區(qū)指正 ? 前些天發(fā)現(xiàn)了一個巨牛的人工智能學習網(wǎng)站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉(zhuǎn)到網(wǎng)站AI學習網(wǎng)站。 當我們開發(fā)一個W

    2024年02月20日
    瀏覽(24)
  • Go語言并發(fā)

    出色的并發(fā)性是Go語言的特色之一 ? 理解并發(fā)與并行 ? 理解進程和線程 ? 掌握Go語言中的Goroutine和channel ? 掌握select分支語句 ? 掌握sync包的應用 并發(fā)與并行的概念這里不再贅述, 可以看看之前java版寫的并發(fā)實踐; 程序、進程與線程這里也不贅述 一個進程可以包括多個線

    2024年02月06日
    瀏覽(20)
  • 【Go】Go語言并發(fā)編程:原理、實踐與優(yōu)化

    在當今的計算機世界,多核處理器和并發(fā)編程已經(jīng)成為提高程序執(zhí)行效率的關(guān)鍵。Go語言作為一門極富創(chuàng)新性的編程語言,憑借其強大的并發(fā)能力,在這方面表現(xiàn)出色。本文將深入探討Go語言并發(fā)編程的原理,通過實際代碼示例展示其應用,并討論可能的優(yōu)化策略。 在了解G

    2024年02月10日
    瀏覽(25)
  • 掌握Go語言:Go語言通道,并發(fā)編程的利器與應用實例(20)

    通道(Channel)是用來在 Go 程序中傳遞數(shù)據(jù)的一種數(shù)據(jù)結(jié)構(gòu)。它是一種類型安全的、并發(fā)安全的、阻塞式的數(shù)據(jù)傳輸方式,用于在不同的 Go 協(xié)程之間傳遞消息。 基本概念 創(chuàng)建通道 :使用 make() 函數(shù)創(chuàng)建一個通道。 發(fā)送數(shù)據(jù) :使用 - 操作符向通道發(fā)送數(shù)據(jù)。 接收數(shù)據(jù) :使用

    2024年03月21日
    瀏覽(35)
  • Go語言并發(fā)模式視角思考

    Go語言并發(fā)模式視角思考

    猶記得2019年中旬進行知識點的學習和demo的練習,熟悉各種語法和并發(fā)調(diào)度的場景, 在2019年末開始參與項目實戰(zhàn)開發(fā)和邏輯梳理 Go語言的接觸也是更多探索和業(yè)務的拆件,做一些雛形工具,來慢慢的孵化業(yè)務生態(tài) 后來陸陸續(xù)續(xù),在主營業(yè)務是PHP的情況下,盡量在業(yè)務腳本的

    2024年01月21日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包