gopcp/example.v2

5.3.6 ConcurrentArray的Set方法实现疑问

darkbloodx opened this issue · 3 comments

chapter5/value/cow/cow.goSet方法:

	newArray := make([]int, array.length)
	copy(newArray, array.val.Load().([]int))
	newArray[index] = elem
	array.val.Store(newArray)

这样实现是否会有并发问题?复制和设值这段是否需要加锁?

Set 中应该是要加锁的,你可以写一个测试用例来看看

一个简单的测试:

	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>

这里不用加锁。原因是,我是原子地取出val中的值的,然后我一个接一个地取出该值中的元素值,在这之后,我才会去修改新值中的元素值。当修改完了之后,我再原子地的一次性的存入一个的值,旧的值永远不会被并发地修改。所以这里不需要加锁。