为什么多协程会出现并发写的问题呢?协程间不是并发运行的吗?应该不会在同一时刻有多个协程操作同一个数据,这块儿不理解希望有大牛给解释解释到底是因为什么,谢谢!
package main
import (
"fmt"
"time"
)
//现在要计算1-20的各个数的阶乘,并且把各个数的阶乘放入到map中。最后显示出来。要求使用goroutine完成
var res = make(map[int]int)
// factorial计算n的阶乘
func factorial(n int) {
tmp := 1
for i := 1; i <= n; i++ {
tmp *= i
}
res[n] = tmp
}
func main() {
//runtime.GOMAXPROCS(1)
for i := 1; i <= 20; i++ {
go factorial(i) // 开启协程计算每个数的阶乘
}
time.Sleep(time.Second * 10)
for i, v := range res {
fmt.Printf("map[%d]=%d\n", i, v)
}
}
报错信息很准确,
concurrent map writes
以下操作可以视作,20个协程并发写
res
。res
是map[int]int
类型,不是并发安全的类型;写的时候调用了
runtime
包的mapassign_fast64(t *maptype, h *hmap, key uint64)
方法返回地址,再对该地址指向的内存赋值;某一个协程对 map 底层进行扩张后,另一个协程可能使用的还是原来的底层结构。
就你这里的,改成用切片?
res = make([]int, 21)