可能遇到的问题及原因
- 数据竞争:在并发环境下,多个 goroutine 同时对切片进行读或写操作时,可能会导致数据竞争。因为 Go 语言的切片不是线程安全的,当一个 goroutine 正在对切片进行深拷贝(涉及读取和写入新切片的操作),而另一个 goroutine 同时修改原切片,就会发生数据竞争。
- 不一致的拷贝结果:由于数据竞争,可能导致深拷贝得到的结果不一致。例如,在拷贝过程中原切片被修改,可能使得新切片的部分数据是旧数据,部分是新数据,破坏了数据的完整性。
解决方案
- 使用互斥锁(Mutex):通过在对切片进行操作(包括深拷贝)时加锁,确保同一时间只有一个 goroutine 能够访问切片,从而避免数据竞争。
- 使用通道(Channel):利用通道来同步 goroutine 之间的操作,使得切片的修改和深拷贝操作按顺序进行,避免并发冲突。
代码示例(使用互斥锁)
package main
import (
"fmt"
"sync"
)
var mu sync.Mutex
func DeepCopy(slice []int) []int {
mu.Lock()
defer mu.Unlock()
newSlice := make([]int, len(slice))
copy(newSlice, slice)
return newSlice
}
func main() {
originalSlice := []int{1, 2, 3, 4, 5}
var wg sync.WaitGroup
var copiedSlices []*[]int
for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
defer wg.Done()
copied := DeepCopy(originalSlice)
copiedSlices = append(copiedSlices, &copied)
}()
}
wg.Wait()
for _, copied := range copiedSlices {
fmt.Println(*copied)
}
}
代码示例(使用通道)
package main
import (
"fmt"
"sync"
)
func DeepCopy(slice []int, resultChan chan []int) {
newSlice := make([]int, len(slice))
copy(newSlice, slice)
resultChan <- newSlice
}
func main() {
originalSlice := []int{1, 2, 3, 4, 5}
var wg sync.WaitGroup
resultChan := make(chan []int, 3)
for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
defer wg.Done()
DeepCopy(originalSlice, resultChan)
}()
}
go func() {
wg.Wait()
close(resultChan)
}()
for copied := range resultChan {
fmt.Println(copied)
}
}