欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2023年10月13日 09:20:31   作者:及爾偕老lp  
這篇文章主要為大家介紹了數(shù)據(jù)競爭和內(nèi)存重分配Golang slice并發(fā)不安全問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

Golang 中的 slice 為什么是并發(fā)不安全的?

一、并發(fā)不安全的

在Go語言中,slice是并發(fā)不安全的,主要有以下兩個原因:數(shù)據(jù)競爭、內(nèi)存重分配。

數(shù)據(jù)競爭:slice底層的結(jié)構(gòu)體包含一個指向底層數(shù)組的指針和該數(shù)組的長度,當(dāng)多個協(xié)程并發(fā)訪問同一個slice時,有可能會出現(xiàn)數(shù)據(jù)競爭的問題。例如,一個協(xié)程在修改slice的長度,而另一個協(xié)程同時在讀取或修改slice的內(nèi)容。

內(nèi)存重分配:在向slice中追加元素時,可能會觸發(fā)slice的擴(kuò)容操作,在這個過程中,如果有其他協(xié)程訪問了slice,就會導(dǎo)致指向底層數(shù)組的指針出現(xiàn)異常。

二、并發(fā)場景

多個協(xié)程同時向 slice 追加元素,會有一部分元素被追加到了舊的底層數(shù)組里,最終 slice 的長度小于目標(biāo)值。

func main() {
    a := make([]int, 0)
    for i := 0; i < 10000; i++ {
        go func(i int) {
            a = append(a, i)
        }(i)
    }
    fmt.Println(len(a)) // 9015 < 10000
}

三、實(shí)現(xiàn) slice 并發(fā)安全

要實(shí)現(xiàn) slice 并發(fā)安全,有兩種方法:加互斥鎖、使用channel串行化操作。

方式一:使用互斥鎖 sync.Mutex

追加元素之前調(diào)用 Lock() 函數(shù)加鎖,追加完后,調(diào)用 Unlock() 解鎖。

func main() {
    var lock sync.Mutex //互斥鎖
    a := make([]int, 0)
    var wg sync.WaitGroup
    for i := 0; i < 10000; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            lock.Lock()
            defer lock.Unlock()
            a = append(a, i)
        }(i)
    }
    wg.Wait()
    fmt.Println(len(a))
    // equal 10000
}

最終 slice 的長度等于目標(biāo)值。

方式二:使用channel串行化操作

生產(chǎn)者生產(chǎn)元素,發(fā)送到通道中,消費(fèi)者從通道中接收元素,追加到 slice 中。使用無緩沖通道,接收方、發(fā)送方必須同時存在,負(fù)責(zé)任意一方都會阻塞。

func main() {
    buffer := make(chan int)
    a := make([]int, 0)
    // 消費(fèi)者
    go func() {
        for v := range buffer {
            a = append(a, v)
        }
    }()
    // 生產(chǎn)者
    var wg sync.WaitGroup
    for i := 0; i < 10000; i++ {
        wg.Add(1)
        go func(i int) {
            defer wg.Done()
            buffer <- i
        }(i)
    }
    wg.Wait()
    fmt.Println(len(a))
    // equal 10000
}

最終 slice 的長度等于目標(biāo)值。

兩種方式的比較

加互斥鎖適合于對性能要求不高的場景,畢竟鎖的粒度太大,這種方式屬于通過共享內(nèi)存來實(shí)現(xiàn)通信。channle 適合于對性能要求大的場景,channle 就是專用于 goroutine 間通信的,這種方式屬于通過通信來實(shí)現(xiàn)共享內(nèi)存。

以上就是數(shù)據(jù)競爭和內(nèi)存重分配Golang slice并發(fā)不安全問題解決的詳細(xì)內(nèi)容,更多關(guān)于Golang slice并發(fā)安全的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 深入理解Go語言中的數(shù)組和切片

    深入理解Go語言中的數(shù)組和切片

    Go語言中的數(shù)組大概相當(dāng)與C/C++中的數(shù)組,固定大小,不能夠動態(tài)擴(kuò)展大小,而切片大概相當(dāng)與C++中的Vector,可以動態(tài)擴(kuò)展大小,當(dāng)大小超過容量時,重新分配一塊內(nèi)存,然后將數(shù)據(jù)復(fù)制到新的內(nèi)存區(qū)域。下面我們通過幾個問題來更好理解golang 的數(shù)組和切片,一起來看看吧。
    2016-09-09
  • MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法

    MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法

    這篇文章主要介紹了MacOS中 VSCode 安裝 GO 插件失敗問題的快速解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 詳解Go中如何進(jìn)行進(jìn)行內(nèi)存優(yōu)化和垃圾收集器管理

    詳解Go中如何進(jìn)行進(jìn)行內(nèi)存優(yōu)化和垃圾收集器管理

    這篇文章主要為大家詳細(xì)介紹了Go中如何進(jìn)行進(jìn)行內(nèi)存優(yōu)化和垃圾收集器管理,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解下
    2023-11-11
  • Golang中文件目錄操作的實(shí)現(xiàn)步驟詳解

    Golang中文件目錄操作的實(shí)現(xiàn)步驟詳解

    在Golang中,文件目錄是指計(jì)算機(jī)文件系統(tǒng)中的文件夾或目錄。目錄是用于組織和存儲文件的一種方式,可以包含文件和其他子目錄,本文主要介紹了Golang中文件目錄操作的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2023-05-05
  • golang之?dāng)?shù)據(jù)驗(yàn)證validator的實(shí)現(xiàn)

    golang之?dāng)?shù)據(jù)驗(yàn)證validator的實(shí)現(xiàn)

    這篇文章主要介紹了golang之?dāng)?shù)據(jù)驗(yàn)證validator的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Golang的strings.Split()踩坑記錄

    Golang的strings.Split()踩坑記錄

    工作中,當(dāng)我們需要對字符串按照某個字符串切分成字符串?dāng)?shù)組數(shù)時,常用到strings.Split(),本文主要介紹了Golang的strings.Split()踩坑記錄,感興趣的可以了解一下
    2022-05-05
  • go語言中嵌套結(jié)構(gòu)體的實(shí)現(xiàn)

    go語言中嵌套結(jié)構(gòu)體的實(shí)現(xiàn)

    在Go語言中,嵌套結(jié)構(gòu)體可定義為一個結(jié)構(gòu)體內(nèi)包含另一個結(jié)構(gòu)體,嵌套可以是值嵌套或指針嵌套,兩者在內(nèi)存分配和修改影響上有顯著區(qū)別,本文就來詳細(xì)的介紹一下,感興趣的可以了解一下
    2024-09-09
  • golang 實(shí)現(xiàn)tcp server端和client端,并計(jì)算RTT時間操作

    golang 實(shí)現(xiàn)tcp server端和client端,并計(jì)算RTT時間操作

    這篇文章主要介紹了golang 實(shí)現(xiàn)tcp server端和client端,并計(jì)算RTT時間操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang算法問題之整數(shù)拆分實(shí)現(xiàn)方法分析

    Golang算法問題之整數(shù)拆分實(shí)現(xiàn)方法分析

    這篇文章主要介紹了Golang算法問題之整數(shù)拆分實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了Go語言數(shù)值運(yùn)算與數(shù)組遍歷相關(guān)操作技巧,需要的朋友可以參考下
    2017-02-02
  • Go語言常見錯誤之將接口定義在實(shí)現(xiàn)方

    Go語言常見錯誤之將接口定義在實(shí)現(xiàn)方

    在Go中,接口起到一個十分關(guān)鍵的角色,它們提供了一種方式來定義對象的行為,而不需要知道對象的具體實(shí)現(xiàn),一個常見的錯誤是在實(shí)現(xiàn)方而不是使用方定義接口,本文將詳細(xì)探討為何這樣做是一個錯誤,以及如何避免它
    2024-01-01

最新評論