亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Go?WaitGroup及Cond底層實(shí)現(xiàn)原理

 更新時(shí)間:2022年08月22日 08:57:41   作者:阿甘與阿Q  
這篇文章主要為大家介紹了Go?WaitGroup及Cond底層實(shí)現(xiàn)原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

WaitGroup

概念

Go標(biāo)準(zhǔn)庫(kù)提供了WaitGroup原語(yǔ), 可以用它來(lái)等待一批 Goroutine 結(jié)束

底層數(shù)據(jù)結(jié)構(gòu)

// A WaitGroup must not be copied after first use.
type WaitGroup struct {
 noCopy noCopy
 state1 [3]uint32
}

其中 noCopy 是 golang 源碼中檢測(cè)禁止拷貝的技術(shù)。如果程序中有 WaitGroup 的賦值行為,使用 go vet 檢查程序時(shí),就會(huì)發(fā)現(xiàn)有報(bào)錯(cuò)。但需要注意的是,noCopy 不會(huì)影響程序正常的編譯和運(yùn)行。

state1主要是存儲(chǔ)著狀態(tài)和信號(hào)量,狀態(tài)維護(hù)了 2 個(gè)計(jì)數(shù)器,一個(gè)是請(qǐng)求計(jì)數(shù)器counter ,另外一個(gè)是等待計(jì)數(shù)器waiter(已調(diào)用 WaitGroup.Wait 的 goroutine 的個(gè)數(shù))

當(dāng)數(shù)組的首地址是處于一個(gè)8字節(jié)對(duì)齊的位置上時(shí),那么就將這個(gè)數(shù)組的前8個(gè)字節(jié)作為64位值使用表示狀態(tài),后4個(gè)字節(jié)作為32位值表示信號(hào)量(semaphore);同理如果首地址沒(méi)有處于8字節(jié)對(duì)齊的位置上時(shí),那么就將前4個(gè)字節(jié)作為semaphore,后8個(gè)字節(jié)作為64位數(shù)值。

使用方法

在WaitGroup里主要有3個(gè)方法:

WaitGroup.Add():可以添加或減少請(qǐng)求的goroutine數(shù)量,Add(n) 將會(huì)導(dǎo)致 counter += n

WaitGroup.Done():相當(dāng)于Add(-1),Done() 將導(dǎo)致 counter -=1,請(qǐng)求計(jì)數(shù)器counter為0 時(shí)通過(guò)信號(hào)量調(diào)用runtime_Semrelease喚醒waiter線程

WaitGroup.Wait():會(huì)將 waiter++,同時(shí)通過(guò)信號(hào)量調(diào)用 runtime_Semacquire(semap)阻塞當(dāng)前 goroutine

func main() {
    var wg sync.WaitGroup
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            println("hello")
        }()
    }
    wg.Wait()
}

Cond

概念

Go標(biāo)準(zhǔn)庫(kù)提供了Cond原語(yǔ),可以讓 Goroutine 在滿足特定條件時(shí)被阻塞和喚醒

底層數(shù)據(jù)結(jié)構(gòu)

type Cond struct {
    noCopy noCopy
    // L is held while observing or changing the condition
    L Locker
    notify  notifyList
    checker copyChecker
}
type notifyList struct {
    wait   uint32
    notify uint32
    lock   uintptr // key field of the mutex
    head   unsafe.Pointer
    tail   unsafe.Pointer
}

主要有4個(gè)字段:

nocopy : golang 源碼中檢測(cè)禁止拷貝的技術(shù)。如果程序中有 WaitGroup 的賦值行為,使用 go vet 檢查程序時(shí),就會(huì)發(fā)現(xiàn)有報(bào)錯(cuò),但需要注意的是,noCopy 不會(huì)影響程序正常的編譯和運(yùn)行

checker:用于禁止運(yùn)行期間發(fā)生拷貝,雙重檢查(Double check)

L:可以傳入一個(gè)讀寫鎖或互斥鎖,當(dāng)修改條件或者調(diào)用Wait方法時(shí)需要加鎖

notify:通知鏈表,調(diào)用Wait()方法的Goroutine會(huì)放到這個(gè)鏈表中,從這里獲取需被喚醒的Goroutine列表

使用方法

在Cond里主要有3個(gè)方法:

  • sync.NewCond(l Locker): 新建一個(gè) sync.Cond 變量,注意該函數(shù)需要一個(gè) Locker 作為必填參數(shù),這是因?yàn)樵?nbsp;cond.Wait() 中底層會(huì)涉及到 Locker 的鎖操作
  • Cond.Wait(): 阻塞等待被喚醒,調(diào)用Wait函數(shù)前需要先加鎖;并且由于Wait函數(shù)被喚醒時(shí)存在虛假喚醒等情況,導(dǎo)致喚醒后發(fā)現(xiàn),條件依舊不成立,因此需要使用 for 語(yǔ)句來(lái)循環(huán)地進(jìn)行等待,直到條件成立為止
  • Cond.Signal(): 只喚醒一個(gè)最先 Wait 的 goroutine,可以不用加鎖
  • Cond.Broadcast(): 喚醒所有Wait的goroutine,可以不用加鎖
package main
import (
    "fmt"
    "sync"
    "sync/atomic"
    "time"
)
var status int64
func main() {
    c := sync.NewCond(&amp;sync.Mutex{})
    for i := 0; i &lt; 10; i++ {
        go listen(c)
    }
    go broadcast(c)
    time.Sleep(1 * time.Second)
}
func broadcast(c *sync.Cond) {
    // 原子操作
    atomic.StoreInt64(&amp;status, 1) 
    c.Broadcast()
}
func listen(c *sync.Cond) {
    c.L.Lock()
    for atomic.LoadInt64(&amp;status) != 1 {
        c.Wait() 
        // Wait 內(nèi)部會(huì)先調(diào)用 c.L.Unlock(),來(lái)先釋放鎖,如果調(diào)用方不先加鎖的話,會(huì)報(bào)錯(cuò)
    }
    fmt.Println("listen")
    c.L.Unlock()
}

以上就是Go WaitGroup及Cond底層實(shí)現(xiàn)原理的詳細(xì)內(nèi)容,更多關(guān)于Go WaitGroup Cond原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Beego中ORM操作各類數(shù)據(jù)庫(kù)連接方式詳細(xì)示例

    Beego中ORM操作各類數(shù)據(jù)庫(kù)連接方式詳細(xì)示例

    這篇文章主要為大家介紹了Beego中ORM操作各類數(shù)據(jù)庫(kù)連接方式詳細(xì)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Golang操作命令行的幾種方式總結(jié)

    Golang操作命令行的幾種方式總結(jié)

    這篇文章主要介紹了Golang操作命令行的幾種方式總結(jié),文章通過(guò)圍主題思想展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • 一文詳解GO如何實(shí)現(xiàn)Redis的AOF持久化

    一文詳解GO如何實(shí)現(xiàn)Redis的AOF持久化

    這篇文章主要為大家詳細(xì)介紹了GO如何實(shí)現(xiàn)Redis的AOF持久化的,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以了解一下
    2023-03-03
  • Golang實(shí)現(xiàn)Redis事務(wù)深入探究

    Golang實(shí)現(xiàn)Redis事務(wù)深入探究

    這篇文章主要介紹了Golang實(shí)現(xiàn)Redis事務(wù)深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • golang gorm 操作mysql及gorm基本用法

    golang gorm 操作mysql及gorm基本用法

    golang 官方的那個(gè)操作mysql的有點(diǎn)麻煩所以就使用了gorm,下面就gorm的使用做下簡(jiǎn)單介紹,感興趣的朋友跟隨小編一起看看吧
    2018-11-11
  • 使用Lumberjack+zap進(jìn)行日志切割歸檔操作

    使用Lumberjack+zap進(jìn)行日志切割歸檔操作

    這篇文章主要介紹了使用Lumberjack+zap進(jìn)行日志切割歸檔操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • 解決Golang小數(shù)float64在實(shí)際工程中加減乘除的精度問(wèn)題

    解決Golang小數(shù)float64在實(shí)際工程中加減乘除的精度問(wèn)題

    這篇文章主要介紹了解決Golang小數(shù)float64在實(shí)際工程中加減乘除的精度問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-03-03
  • go實(shí)現(xiàn)反轉(zhuǎn)鏈表

    go實(shí)現(xiàn)反轉(zhuǎn)鏈表

    這篇文章主要介紹了go實(shí)現(xiàn)反轉(zhuǎn)鏈表的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • 深入講解Go語(yǔ)言中函數(shù)new與make的使用和區(qū)別

    深入講解Go語(yǔ)言中函數(shù)new與make的使用和區(qū)別

    大家都知道Go語(yǔ)言中的函數(shù)new與函數(shù)make一直是新手比較容易混淆的東西,看著相似,但其實(shí)不同,不過(guò)解釋兩者之間的不同也非常容易,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言中函數(shù)new與make區(qū)別的相關(guān)資料,需要的朋友可以參考下。
    2017-10-10
  • golang定時(shí)任務(wù)cron項(xiàng)目實(shí)操指南

    golang定時(shí)任務(wù)cron項(xiàng)目實(shí)操指南

    Go實(shí)現(xiàn)的cron 表達(dá)式的基本語(yǔ)法跟linux 中的 crontab基本是類似的,下面這篇文章主要給大家介紹了關(guān)于golang定時(shí)任務(wù)cron項(xiàng)目實(shí)操的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12

最新評(píng)論