Is Append Not Thread-Safe for Concurrent Use by Multiple Goroutines?
When using goroutines to concurrently append data to a slice within a loop, you may encounter inconsistencies, such as missing or duplicated elements. This scenario raises the question of whether the append function is not thread-safe for concurrent use by multiple goroutines.
The Answer: Data Races and Lack of Thread Safety
In Go, no value is safe for concurrent read/write, including slices (or more specifically, slice headers). When multiple goroutines attempt to concurrently modify the same slice, data races occur, potentially leading to unexpected behavior.
Data Race Verification
You can run your code with the -race option to confirm the presence of data races:
go run -race play.go
Solution: Synchronization
To resolve this issue and ensure data consistency, you need to synchronize access to the slice when writing elements concurrently. This can be achieved using a sync.Mutex:
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()
By acquiring the mutex before appending to the slice and releasing it afterward, you ensure that only one goroutine has write access at a time, preventing data corruption.
Conclusion
While slice elements behave as distinct variables and can be modified concurrently, slice headers are not inherently thread-safe. To ensure safe and consistent concurrent write operations, it is crucial to employ synchronization mechanisms such as mutexes or channels when modifying slice headers within goroutines.
The above is the detailed content of Is Append Function Thread-Safe for Concurrent Goroutine Usage?. For more information, please follow other related articles on the PHP Chinese website!