首頁  >  文章  >  後端開發  >  為什麼附加到並發 Goroutine 中的切片不是線程安全的?

為什麼附加到並發 Goroutine 中的切片不是線程安全的?

Linda Hamilton
Linda Hamilton原創
2024-11-10 00:49:02762瀏覽

Why is Appending to a Slice in Concurrent Goroutines Not Thread-Safe?

併發切片:附加不是線程安全的

問題:

問題:
destSlice := make([]myClass, 0)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        destSlice = append(destSlice, tmpObj)
    }(myObject)
}
wg.Wait()

考慮以下程式碼在這個程式碼> for 迴圈中使用多個goroutine附加到切片:

有時,此程式碼會在 destSlice 中產生遺失或空白的數據,或不包含 sourceSlice 中的所有元素。為什麼會發生這種情況?

答案:

go run -race play.go
在 Go 中,當進行並發讀/寫入操作(包括切片)時,所有值都容易受到資料爭用的影響。這是由於切片標頭(其中包含有關切片的容量和長度的信息)的實現方式所致。

使用-race 標誌運行程式碼將確認資料爭用的存在:

解決方案:
var (
    mu        = &sync.Mutex{}
    destSlice = make([]myClass, 0)
)

var wg sync.WaitGroup
for _, myObject := range sourceSlice {
    wg.Add(1)
    go func(closureMyObject myClass) {
        defer wg.Done()
        var tmpObj myClass
        tmpObj.AttributeName = closureMyObject.AttributeName
        mu.Lock()
        destSlice = append(destSlice, tmpObj)
        mu.Unlock()
    }(myObject)
}
wg.Wait()

為了避免資料競爭並確保附加到切片時的並發安全,應使用同步原語(例如sync.Mutex)來保護寫入destSlice值:或者,考慮使用通道來促進並發附加過程。

以上是為什麼附加到並發 Goroutine 中的切片不是線程安全的?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn