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

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è)讀寫(xiě)鎖或互斥鎖,當(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)文章

  • Go語(yǔ)言中append函數(shù)用法分析

    Go語(yǔ)言中append函數(shù)用法分析

    這篇文章主要介紹了Go語(yǔ)言中append函數(shù)用法,對(duì)比使用append函數(shù)與不使用append函數(shù)的兩個(gè)實(shí)例,詳細(xì)分析了Go語(yǔ)言中append函數(shù)的功能,需要的朋友可以參考下
    2015-02-02
  • Go語(yǔ)言的type?func()用法詳解

    Go語(yǔ)言的type?func()用法詳解

    在Go語(yǔ)言中,函數(shù)的基本組成為:關(guān)鍵字func、函數(shù)名、參數(shù)列表、返回值、函數(shù)體和返回語(yǔ)句,這篇文章主要介紹了Go語(yǔ)言的type?func()用法,需要的朋友可以參考下
    2022-03-03
  • golang中配置?sql.DB獲得更好的性能

    golang中配置?sql.DB獲得更好的性能

    這篇文章主要介紹了golang中如何配置?sql.DB獲得更好的性能,在這篇文章中,我想準(zhǔn)確解釋這些設(shè)置的作用,并展示它們可能產(chǎn)生的(積極和消極)影響,需要的朋友可以參考下
    2023-10-10
  • Golang中的強(qiáng)大Web框架Fiber詳解

    Golang中的強(qiáng)大Web框架Fiber詳解

    在不斷發(fā)展的Web開(kāi)發(fā)領(lǐng)域中,選擇正確的框架可以極大地影響項(xiàng)目的效率和成功,介紹一下Fiber,這是一款令人印象深刻的Golang(Go語(yǔ)言)Web框架,在本文中,我們將深入了解Fiber的世界,探討其獨(dú)特的特性,并理解為什么它在Go生態(tài)系統(tǒng)中引起了如此大的關(guān)注
    2023-10-10
  • 一文搞懂Go語(yǔ)言中文件的讀寫(xiě)與創(chuàng)建

    一文搞懂Go語(yǔ)言中文件的讀寫(xiě)與創(chuàng)建

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中文件是如何實(shí)現(xiàn)讀寫(xiě)與創(chuàng)建的,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定幫助,需要的可以參考一下
    2022-07-07
  • Golang操作excel的技巧與方法

    Golang操作excel的技巧與方法

    在Golang中操作Excel可以包括讀取、寫(xiě)入和編輯Excel文件,你可以定義函數(shù)或方法來(lái)執(zhí)行這些操作,本文給大家介紹了Golang操作excel的技巧與方法,文中有詳細(xì)的代碼講解,需要的朋友可以參考下
    2024-05-05
  • Golang實(shí)現(xiàn)文件傳輸功能

    Golang實(shí)現(xiàn)文件傳輸功能

    這篇文章主要為大家詳細(xì)介紹了Golang實(shí)現(xiàn)文件傳輸功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Golang sync.Pool的源碼解析

    Golang sync.Pool的源碼解析

    Pool是用于存放臨時(shí)對(duì)象的集合,這些對(duì)象是為了后續(xù)的使用,以達(dá)到復(fù)用對(duì)象的效果,本文將詳解解析sync.Pool 源碼,需要的朋友可以參考下
    2023-05-05
  • Go語(yǔ)言中序列化與反序列化示例詳解

    Go語(yǔ)言中序列化與反序列化示例詳解

    我們的數(shù)據(jù)對(duì)象要在網(wǎng)絡(luò)中傳輸或保存到文件,就需要對(duì)其編碼和解碼動(dòng)作,Go語(yǔ)言當(dāng)然也支持所有這些編碼格式,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言中序列化與反序列化的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • Golang變量直接初始化的方法詳解

    Golang變量直接初始化的方法詳解

    在 Go 語(yǔ)言中,我們常用的數(shù)據(jù)結(jié)構(gòu)有在Go語(yǔ)言中,你可以初始化不同的數(shù)據(jù)結(jié)構(gòu),例如數(shù)組、切片、結(jié)構(gòu)體、指針、map等,本文將給大家介紹一下Golang變量直接初始化的方法,需要的朋友可以參考下
    2023-08-08

最新評(píng)論

洛浦县| 潍坊市| 华坪县| 富阳市| 开阳县| 民丰县| 武平县| 张家口市| 北流市| 江北区| 澄城县| 岫岩| 巧家县| 安陆市| 萝北县| 东阳市| 丰台区| 吴堡县| 黎城县| 隆昌县| 建瓯市| 湖北省| 鹤峰县| 枝江市| 富蕴县| 浑源县| 沙湾县| 慈溪市| 常德市| 大城县| 濉溪县| 深泽县| 大悟县| 中卫市| 夏津县| 松阳县| 望城县| 正宁县| 密山市| 铜山县| 汝南县|