并发安全
golang的slice和map是常用的数据结构,为了降低性能损耗,slice和map并没有相应的设计来保证并发安全。
slice
- 验证非并发安全
起n个goroutine并发的超slice中append数据,n个goroutine都结束后,打印slice的长度。
package main
import (
"fmt"
"sync"
)
func main() {
var (
slc = []int{}
n = 10000
wg sync.WaitGroup
)
wg.Add(n)
for i := 0; i < n; i++ {
go func() {
slc = append(slc, i)
wg.Done()
}()
}
wg.Wait()
fmt.Println("len:", len(slc))
fmt.Println("done")
}
// Output:
len: 8586
done
真实的输出并没有达到我们的预期,len(slice) < n。 问题出在哪?我们都知道slice是对数组一个连续片段的引用,当slice长度增加的时候,可能底层的数组会被换掉。当出在换底层数组之前,切片同时被多个goroutine拿到,并执行append操作。那么很多goroutine的append结果会被覆盖,导致n个gouroutine append后,长度小于n。
-
<