5.3.6 ConcurrentArray的Set方法实现疑问
darkbloodx opened this issue · 3 comments
darkbloodx commented
chapter5/value/cow/cow.go
中Set
方法:
newArray := make([]int, array.length)
copy(newArray, array.val.Load().([]int))
newArray[index] = elem
array.val.Store(newArray)
这样实现是否会有并发问题?复制和设值这段是否需要加锁?
lsytj0413 commented
Set 中应该是要加锁的,你可以写一个测试用例来看看
lsytj0413 commented
一个简单的测试:
arr := sync.NewConcurrentArray(10)
l := 10
var wg ssync.WaitGroup
wg.Add(l)
for i := 0; i < l; i++ {
go func(i int) {
defer wg.Done()
for j := 0; j < 1000; j++ {
err := arr.Set(uint32(i), j)
if err != nil {
fmt.Println(err)
}
}
}(i)
}
wg.Wait()
for i := 0; i < l; i++ {
fmt.Println(arr.Get(uint32(i)))
}
在我本地的输出为:
999 <nil> 998 <nil> 944 <nil> 999 <nil> 974 <nil> 914 <nil> 847 <nil> 954 <nil> 922 <nil> 999 <nil>
hyper0x commented
这里不用加锁。原因是,我是原子地取出val中的值的,然后我一个接一个地取出该值中的元素值,在这之后,我才会去修改新值中的元素值。当修改完了之后,我再原子地的、一次性的存入一个新的值,旧的值永远不会被并发地修改。所以这里不需要加锁。