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

Go語言擴(kuò)展原語之Semaphore的用法詳解

 更新時(shí)間:2023年07月20日 15:52:50   作者:碼一行  
Go語言的擴(kuò)展包中提供了帶權(quán)重的信號量?semaphore.Weighted,讓我們可以按照不同的權(quán)重管理資源的訪問,下面小編就來和大家聊聊它們的具體用法吧

概述

信號量是并發(fā)編程中常見的一種同步機(jī)制,在需要控制訪問資源的進(jìn)程數(shù)量時(shí)就會(huì)用到信號量,它會(huì)保證持有的計(jì)數(shù)器在 0 到初始化的權(quán)重之間波動(dòng)。

  • 每次獲取的資源都會(huì)將信號量中的計(jì)數(shù)器減去對應(yīng)的數(shù)值,在釋放時(shí)重新加回來
  • 當(dāng)遇到計(jì)數(shù)器大于信號量大小時(shí),會(huì)進(jìn)入休眠等待其他線程釋放信號

Go語言的擴(kuò)展包中提供了帶權(quán)重的信號量 semaphore.Weighted,我們可以按照不同的權(quán)重管理資源的訪問,這種結(jié)構(gòu)體暴露了 4 個(gè)方法:

  • semaphore.NewWeighted —— 用于創(chuàng)建新的信號量
  • semaphore.Weighted.Acquire —— 阻塞地獲取指定權(quán)重的資源,如果當(dāng)前沒有空閑資源,會(huì)陷入休眠等待
  • semaphore.Weighted.TryAcquire —— 非阻塞地獲取指定權(quán)重的資源,如果當(dāng)前沒有空閑資源,會(huì)直接返回 false
  • semaphore.Weighted.Relesae —— 用于釋放指定權(quán)重的資源

結(jié)構(gòu)體

semaphore.NewWeighted 方法能提供傳入的大量權(quán)重創(chuàng)建一個(gè)指向 semaphore.Weighted 結(jié)構(gòu)體的指針:

func NewWeighted(n int64) *Weighted {
    w := &Weighted{size: n}
    return w
}
type Weighted struct {
    size    int64
    cur     int64
    mu      sync.Mutex
    waiters list.list
}

semaphore.Weighted 結(jié)構(gòu)體中包含一個(gè) waiters 列表,其中存儲(chǔ)著等待獲取資源的 Goroutine。除此之外,它還包含當(dāng)前信號量的上限以及一個(gè)計(jì)數(shù)器 cur, 這個(gè)計(jì)數(shù)器的范圍就是 [0,size]

信號量中的計(jì)數(shù)器會(huì)隨著用戶對資源的訪問和釋放而改變,引入的權(quán)重概念能夠提供更細(xì)粒度的資源訪問控制,盡可能滿足常見用例。

獲取

semaphore.Weighted.Acquire 方法能用于獲取指定權(quán)重的資源,其中包含 3 中情況:

  • 當(dāng)信號量中剩余資源大于獲取的資源并且沒有等待的 Goroutine 時(shí),會(huì)直接獲取信號量
  • 當(dāng)需要獲取的信號量大于 semaphore.Weighted 的上限時(shí),由于不可能滿足條件,因此會(huì)直接返回錯(cuò)誤
  • 遇到其他情況時(shí),會(huì)將當(dāng)前 Goroutine 加入等待列表,并通過 select 等待調(diào)度器喚醒當(dāng)前 Goroutine,Goroutine 被喚醒后會(huì)獲取信號量
func (s *Weighted) Acquire(ctx context.Context, n int64) error {
    if s.size - s.cur >= n && len(s.waiters) == 0 {
        s.cur += n
        return nil
    }
    ...
    ready := make(chan struct{})
    w := waiter{n: n, ready: ready}
    elem := s.waiters.PushBack(w)
    select {
    case <-ctx.Done():
        err := ctx.Err()
        select {
        case <-ready:
            err = nil
        default:
            s.waiters.Remove(elem)
        }
        return err
    case <-ready:
        return nil
    }
}

另一個(gè)用于獲取信號量的方法 semaphore.Weighted.TryAcquire 只會(huì)非阻塞地判斷當(dāng)前信號量是否有充足的資源,如果有,會(huì)立刻返回 true, 否則會(huì)返回 false :

func (s *Weighted) TryAcquire(n int64) bool {
    s.mu.Lock()
    success := s.size-s.cur >= n && len(s.waiters) == 0
    if success {
        s.cur += n
    }
    s.mu.Unlock()
    return success
}

因?yàn)?semaphore.Weighted.TryAcquire 不會(huì)等待資源的釋放,所以可能更適用于一些對延時(shí)敏感、用戶需要立刻感知結(jié)果的場景

釋放

當(dāng)我們要釋放信號量時(shí),semaphore.Weighted.Relesae 方法會(huì)從頭到尾遍歷 waiters 列表中全部的等待者,如果釋放資源后的信號量有充足的剩余資源,就會(huì)通過 Channel 喚醒指定的 Goroutine:

func (c *Weighted) Relesae(n int64) {
    s.mu.Lock()
    s.cur -= n
    for {
        next := w.waiters.Front()
        if next == nil {
            break
        }
        w := next.Value.(waiter)
        if s.size-s.cur < w.n {
            break
        }
        s.cur += w.n
        s.waiters.Remove(next)
        close(w.ready)
    }
    s.mu.Unlock()
}

當(dāng)然,也可能會(huì)出現(xiàn)剩余資源無法喚醒 Channel 的情況,這時(shí)當(dāng)前方法釋放鎖之后會(huì)直接返回。

通過 semaphore.Weighted.Relesae 的分析我們可以發(fā)現(xiàn),如果一個(gè)信號量需要占用的資源非常多,它可能會(huì)長時(shí)間無法獲取鎖,這也是 semaphore.Weighted.Acquire 引入上下文參數(shù)的原因,即為信號量的獲取設(shè)置超時(shí)時(shí)間。

小結(jié)

帶權(quán)重的信號量確實(shí)有更多的應(yīng)用場景,,這也是Go語言對外提供的唯一信號量實(shí)現(xiàn),使用過程中需要注意以下幾個(gè)問題:

  • semaphore.Weighted.Acquire 和 semaphore.Weighted.TryAcquire 都可以適用于獲取資源,前者會(huì)阻塞獲取信號量,后者會(huì)非阻塞獲取信號量
  • semaphore.Weighted.Relesae 方法會(huì)按照先進(jìn)先出的順序喚醒可以被喚醒的 Goroutine
  • 如果一個(gè) Goroutine 獲取了較多的資源,由于 semaphore.Weighted.Relesae 的釋放策略可能會(huì)等待較長時(shí)間

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

相關(guān)文章

  • 數(shù)據(jù)競爭和內(nèi)存重分配Golang slice并發(fā)不安全問題解決

    數(shù)據(jù)競爭和內(nèi)存重分配Golang slice并發(fā)不安全問題解決

    這篇文章主要為大家介紹了數(shù)據(jù)競爭和內(nèi)存重分配Golang slice并發(fā)不安全問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • Windows10系統(tǒng)下安裝Go環(huán)境詳細(xì)步驟

    Windows10系統(tǒng)下安裝Go環(huán)境詳細(xì)步驟

    Go語言是谷歌推出的一款全新的編程語言,可以在不損失應(yīng)用程序性能的情況下極大的降低代碼的復(fù)雜性,這篇文章主要給大家介紹了關(guān)于Windows10系統(tǒng)下安裝Go環(huán)境的詳細(xì)步驟,需要的朋友可以參考下
    2023-11-11
  • Golang?動(dòng)態(tài)腳本調(diào)研詳解

    Golang?動(dòng)態(tài)腳本調(diào)研詳解

    這篇文章主要為大家介紹了Golang?動(dòng)態(tài)腳本調(diào)研詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • golang壓縮與解壓縮文件的示例代碼

    golang壓縮與解壓縮文件的示例代碼

    這篇文章主要給大家介紹了golang壓縮與解壓縮文件,文中通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-02-02
  • Golang實(shí)現(xiàn)Redis分布式鎖(Lua腳本+可重入+自動(dòng)續(xù)期)

    Golang實(shí)現(xiàn)Redis分布式鎖(Lua腳本+可重入+自動(dòng)續(xù)期)

    本文主要介紹了Golang分布式鎖實(shí)現(xiàn),采用Redis+Lua腳本確保原子性,持可重入和自動(dòng)續(xù)期,用于防止超賣及重復(fù)下單,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-05-05
  • Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換

    Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換

    在軟件開發(fā)的世界里,數(shù)據(jù)類型轉(zhuǎn)換是一項(xiàng)基礎(chǔ)而重要的技能,尤其在Go語言這樣類型嚴(yán)格的語言中,正確高效地進(jìn)行類型轉(zhuǎn)換對于性能優(yōu)化和代碼質(zhì)量至關(guān)重要,本文給大家介紹了Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換,需要的朋友可以參考下
    2024-02-02
  • Go語言中處理錯(cuò)誤的技巧分享

    Go語言中處理錯(cuò)誤的技巧分享

    編寫 Go 語言程序時(shí),有效地處理錯(cuò)誤是至關(guān)重要的,Go 語言提供了一些強(qiáng)大的工具和模式來處理錯(cuò)誤,本文將介紹這些方法,以便編寫健壯的 Go 代碼,更好地處理錯(cuò)誤,需要的朋友可以參考下
    2023-09-09
  • golang包循環(huán)引用的幾種解決方案總結(jié)

    golang包循環(huán)引用的幾種解決方案總結(jié)

    golang有包循環(huán)引用問題,用過的應(yīng)該都知道,下面這篇文章主要給大家介紹了關(guān)于golang包循環(huán)引用的幾種解決方案,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09
  • goland安裝1.7版本報(bào)錯(cuò)Unpacked?SDK?is?corrupted解決

    goland安裝1.7版本報(bào)錯(cuò)Unpacked?SDK?is?corrupted解決

    這篇文章主要為大家介紹了goland安裝1.7版本報(bào)錯(cuò)Unpacked?SDK?is?corrupted解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Go語言實(shí)現(xiàn)IP段范圍校驗(yàn)示例

    Go語言實(shí)現(xiàn)IP段范圍校驗(yàn)示例

    這篇文章主要介紹了Go語言實(shí)現(xiàn)IP段范圍校驗(yàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09

最新評論

余姚市| 进贤县| 金秀| 安乡县| 出国| 隆德县| 巩留县| 石河子市| 珲春市| 松溪县| 江西省| 清远市| 陕西省| 商河县| 黑水县| 通渭县| 镇雄县| 东兰县| 苍溪县| 蓬莱市| 塘沽区| 宜章县| 安远县| 客服| 岳池县| 扶余县| 桂林市| 原平市| 琼海市| 柏乡县| 勐海县| 陈巴尔虎旗| 界首市| 祥云县| 广丰县| 新津县| 连山| 梁平县| 宁津县| 元朗区| 汾阳市|