非线程安全的例子
slice
我们使用多个 goroutine 对类型为 slice 的变量进行操作,看看结果会变的怎么样。
如下:
func main() {
var s []string
for i := 0; i < 9999; i++ {
go func() {
s = append(s, "脑子进煎鱼了")
}()
}
fmt.Printf("进了 %d 只煎鱼", len(s))
}
输出结果:
// 第一次执行
进了 5790 只煎鱼
// 第二次执行
进了 7370 只煎鱼
// 第三次执行
进了 6792 只煎鱼
你会发现无论你执行多少次,每次输出的值大概率都不会一样。也就是追加进 slice 的值,出现了覆盖的情况。
因此在循环中所追加的数量,与最终的值并不相等。且这种情况,是不会报错的,是一个出现率不算高的隐式问题。
这个产生的主要原因是程序逻辑本身就有问题,同时读取到相同索引位,自然也就会产生覆盖的写入了。
map
同样针对 map 也如法炮制一下。重复针对类型为 map 的变量进行写入。
如下:
func main() {
s := make(map[string]string)
for i := 0; i < 99; i++ {
go func() {
s["煎鱼"] = "吸鱼"
}()
}
fmt.Printf("进了 %d 只煎鱼", len(s))
}
输出结果:
fatal error: concurrent map writes
goroutine 18 [running]:
runtime.throw(0x10cb861