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

解析Go的Waitgroup和鎖的問題

 更新時間:2021年05月18日 09:27:32   作者:呦呦鹿鳴  
大家在學(xué)習go語言的時候,都知道go語言支持并發(fā),使用 goroutine,使用關(guān)鍵字 go 即可,接下來通過本文給大家分享Go的Waitgroup和鎖的問題,需要的朋友可以參考下

學(xué) Go 的時候知道 Go 語言支持并發(fā),最簡單的方法是通過 go 關(guān)鍵字開啟 goroutine 即可??稍诠ぷ髦校玫氖?sync 包的 WaitGroup,然而這樣還不夠,當多個 goroutine 同時訪問一個變量時,還要考慮如何保證這些 goroutine 之間不會相互影響,這就又使用到了 sync 的 Mutex。它們是如何串起來的呢?

一、Goroutinue

先說 goroutine,我們都知道它是 Go 中的輕量級線程。Go 程序從 main 包的 main() 函數(shù)開始,在程序啟動時,Go 程序就會為 main() 函數(shù)創(chuàng)建一個默認的 goroutine。使用 goroutine,使用關(guān)鍵字 go 即可。

package main
import (
    "fmt"
)
func main() {
    // 并發(fā)執(zhí)行程序
    go running()
}
func running() {
    fmt.Println("Goroutine")
}

執(zhí)行代碼會發(fā)現(xiàn)沒有我們預(yù)期的“Goroutine”輸出,這是因為當前的程序是一個單線程的程序,main 函數(shù)只要執(zhí)行后,就不會再管其他線程在做什么事情,程序就自動退出了。解決辦法是加一個 sleep 函數(shù),讓 main 函數(shù)等待 running 函數(shù)執(zhí)行完畢后再退出。我們假設(shè) running 函數(shù)里的代碼執(zhí)行需要 2 秒,因此讓 main 函數(shù)等待 3 秒再退出。

package main
import (
    "fmt"
    "time"
)
func main() {
    // 并發(fā)執(zhí)行程序
    go running()
    time.Sleep(3 * time.Second)
}
func running() {
    fmt.Println("Goroutine")
}

再次執(zhí)行代碼,終端輸出了我們想要的“Goroutine”字符串。

二、WaitGroup

上面我們是假設(shè)了 running 函數(shù)執(zhí)行需要 2 秒,可如果執(zhí)行需要 10 秒甚至更長時間,不知道 goroutin 什么時候結(jié)束,難道還要 main 函數(shù) sleep 更多的秒數(shù)嗎?就不能讓 running 函數(shù)執(zhí)行完去通知 main 函數(shù),main 函數(shù)收到信號自動退出嗎?還真可以!可以使用 sync 包的 Waitgroup 判斷一組任務(wù)是否完成。

WatiGroup 能夠一直等到所有的 goroutine 執(zhí)行完成,并且阻塞主線程的執(zhí)行,直到所有的 goroutine 執(zhí)行完成。它有 3 個方法:

  • Add():給計數(shù)器添加等待 goroutine 的數(shù)量。
  • Done():減少 WaitGroup 計數(shù)器的值,應(yīng)在協(xié)程的最后執(zhí)行。
  • Wait():執(zhí)行阻塞,直到所有的 WaitGroup 數(shù)量變成 0

一個簡單的示例如下:

package main 
import ( 
    "fmt” 
    "sync” 
    “time"
) 

func process(i int, wg *sync.WaitGroup) { 
    fmt.Println("started Goroutine ", i) 
    time.Sleep(2 * time.Second) 
    fmt.Printf("Goroutine %d ended\n", i) 
    wg.Done() 
} 

func main() { 
    var wg sync.WaitGroup 
    for i := 0; i < 3; i++ { 
        wg.Add(1) 
        go process(i, &wg) 
    } 
    wg.Wait() 
    fmt.Println("All go routines finished executing”) 
}
//main函數(shù)也可以寫成如下方式
func main() {
    var wg sync.WaitGroup
    wg.Add(3) //設(shè)置計數(shù)器,數(shù)值即為goroutine的個數(shù)
    go process(1, &wg)
    go process(2, &wg)
    go process(3, &wg)
    wg.Wait() //主goroutine阻塞等待計數(shù)器變?yōu)?
    fmt.Println("All goroutines finished executing")
}

命令行輸出如下:

deer@192 src % go run hello.go //第1次
started Goroutine  3
started Goroutine  1
started Goroutine  2
Goroutine 2 ended
Goroutine 1 ended
Goroutine 3 ended
All goroutines finished executing

deer@192 src % go run hello.go //第2次
started Goroutine  3
started Goroutine  1
started Goroutine  2
Goroutine 1 ended
Goroutine 2 ended
Goroutine 3 ended
All goroutines finished executing

deer@192 src % go run hello.go //第3次
started Goroutine  3
started Goroutine  2
started Goroutine  1
Goroutine 3 ended
Goroutine 1 ended
Goroutine 2 ended
All goroutines finished executing

簡單的說,上面程序中 wg 內(nèi)部維護了一個計數(shù)器,激活了 3 個 goroutine:
1)每次激活 goroutine 之前,都先調(diào)用 Add() 方法增加一個需要等待的 goroutine 計數(shù)。
2)每個 goroutine 都運行 process() 函數(shù),這個函數(shù)在執(zhí)行完成時需要調(diào)用 Done() 方法來表示 goroutine 的結(jié)束。
3)激活 3 個 goroutine 后,main 的 goroutine 會執(zhí)行到 Wait(),由于每個激活的 goroutine 運行的 process() 都需要睡眠 2 秒,所以 main 的 goroutine 在 Wait() 這里會阻塞一段時間(大約2秒),
4)當所有 goroutine 都完成后,計數(shù)器減為 0,Wait() 將不再阻塞,于是 main 的 goroutine 得以執(zhí)行后面的 Println()。

這里需要注意:
1)process() 中使用指針類型的 *sync.WaitGroup 作為參數(shù),表示這 3 個 goroutine 共享一個 wg,才能知道這 3 個 goroutine 都完成了。如果這里使用值類型的 sync.WaitGroup 作為參數(shù),意味著每個 goroutine 都拷貝一份 wg,每個 goroutine 都使用自己的 wg,main goroutine將會永久阻塞而導(dǎo)致產(chǎn)生死鎖。
2)Add() 設(shè)置的數(shù)量必須與實際等待的 goroutine 個數(shù)一致,也就是和Done的調(diào)用數(shù)量必須相等,否則會panic,報錯信息如下:

fatal error: all goroutines are asleep - deadlock!

三、鎖

當多個 goroutine 同時操作一個變量時,會存在數(shù)據(jù)競爭,導(dǎo)致最后的結(jié)果與期待的不符,解決辦法就是加鎖。Go 中的 sync 包 實現(xiàn)了兩種鎖:Mutex 和 RWMutex,前者為互斥鎖,后者為讀寫鎖,基于 Mutex 實現(xiàn)。當我們的場景是寫操作為主時,可以使用 Mutex 來加鎖、解鎖。

var lock sync.Mutex //聲明一個互斥鎖
 lock.Lock() //加鎖
//code...
 lock.Unlock() //解鎖

互斥鎖其實就是每個線程在對資源操作前都嘗試先加鎖,成功加鎖才能操作,操作結(jié)束后再解鎖。也就是說,使用了互斥鎖,同一時刻只能有一個 goroutine 在執(zhí)行。

以上就是解析Go的Waitgroup和鎖的問題的詳細內(nèi)容,更多關(guān)于Go的Waitgroup和鎖的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Go 使用Unmarshal將json賦給struct出錯的原因及解決

    Go 使用Unmarshal將json賦給struct出錯的原因及解決

    這篇文章主要介紹了Go 使用Unmarshal將json賦給struct出錯的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • 深入理解Golang channel的應(yīng)用

    深入理解Golang channel的應(yīng)用

    channel是用于 goroutine 之間的同步、通信的數(shù)據(jù)結(jié)構(gòu)。它為程序員提供了更高一層次的抽象,封裝了更多的功能,這樣并發(fā)編程變得更加容易和安全。本文通過示例為大家詳細介紹了channel的應(yīng)用,需要的可以參考一下
    2022-10-10
  • Golang集成FFmpeg的音視頻處理的實現(xiàn)

    Golang集成FFmpeg的音視頻處理的實現(xiàn)

    FFmpeg是一個開源的音視頻處理工具,廣泛用于視頻轉(zhuǎn)換、截圖、處理和流媒體推送等操作,本文主要介紹了Golang集成FFmpeg的音視頻處理的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2025-02-02
  • go語言K8S?的?informer機制淺析

    go語言K8S?的?informer機制淺析

    這篇文章為大家主要介紹了go語言K8S?的?informer機制淺析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Go語言等待組sync.WaitGrou的使用示例

    Go語言等待組sync.WaitGrou的使用示例

    本文主要介紹了Go語言等待組sync.WaitGrou的使用示例,sync.WaitGroup只有3個方法,Add(),Done(),Wait(),下面就來具體的介紹一下如何使用,感興趣的可以了解一下
    2024-08-08
  • 詳解Go語言中select語句的常見用法

    詳解Go語言中select語句的常見用法

    這篇文章主要是來和大家介紹一下Go語言中select?語句的常見用法,以及在使用過程中的注意事項,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下
    2023-07-07
  • go使用Viper管理配置文件的方法步驟

    go使用Viper管理配置文件的方法步驟

    在項目開發(fā)中,需要把一些配置配置提取出來,方便配置和管理,可以使用Viper工具,Viper 是 Go 應(yīng)用程序的完整配置解決方案,也支持從環(huán)境變量中讀取,本文給大家介紹了go使用Viper管理配置文件的方法步驟,需要的朋友可以參考下
    2024-07-07
  • Golang 負載均衡算法實現(xiàn)示例

    Golang 負載均衡算法實現(xiàn)示例

    在Go語言中,負載均衡算法通常由代理、反向代理或者應(yīng)用層負載均衡器來實現(xiàn),在這些實現(xiàn)中,有一些經(jīng)典的負載均衡算法,跟隨本文來一一探究
    2024-01-01
  • Golang字符串常用函數(shù)的使用

    Golang字符串常用函數(shù)的使用

    Golang提供了許多內(nèi)置的字符串函數(shù),這些函數(shù)可在處理字符串數(shù)據(jù)時幫助執(zhí)行一些操作,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Golang定時器的2種實現(xiàn)方法與區(qū)別

    Golang定時器的2種實現(xiàn)方法與區(qū)別

    這篇文章主要給大家介紹了關(guān)于Golang定時器的2種實現(xiàn)方法與區(qū)別的相關(guān)資料,文中通過圖文介紹的非常詳細,對大家的學(xué)習或者工作具有一定的參考學(xué)習價值,需要的朋友們下面隨著小編來一起學(xué)習學(xué)習吧
    2021-02-02

最新評論

海南省| 苏尼特左旗| 长春市| 收藏| 阳曲县| 长阳| 奇台县| 商洛市| 新泰市| 介休市| 丹巴县| 皋兰县| 临海市| 石景山区| 甘洛县| 安庆市| 澎湖县| 莱州市| 惠州市| 辽阳县| 黄冈市| 镇远县| 成安县| 灯塔市| 萍乡市| 天等县| 会泽县| 普兰县| 茌平县| 错那县| 威信县| 拉孜县| 谢通门县| 乌兰浩特市| 微博| 新巴尔虎左旗| 毕节市| 宜川县| 易门县| 蕲春县| 天台县|