併發切片:附加不是線程安全的
問題:
問題: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中文網其他相關文章!