go map 并发 concurrent 锁
作者:互联网
var (
count int
)
//全局变量并发写 导致计数错误
func vari() {
for i := 0; i < 10000; i++ {
go func(i int) {
count++
fmt.Println("count:", count)
}(i)
}
fmt.Println(count)
}
//Output:
/** 总共只有9571行,正确的话应该有 10000行
count: 1
...
count: 9616
count: 9617
7205
count: 9607
count: 9609
count: 9600
结束**/
var (
count int
l = sync.Mutex{}
)
//全局变量并发写 加锁后 仍然错误
func vari() {
for i := 0; i < 10000; i++ {
go func(i int) {
l.Lock()
defer l.Unlock()
count++
fmt.Println("count:", count)
}(i)
}
fmt.Println(count)
}
//Output
/** 对全局变量加锁后 只有4465行 并发问题依然存在
count: 1
count: 2
count: 3
...
count: 4460
count: 4461
count: 4462
count: 4463
4463
count: 4464
结束**/
//可能会 runtime error, 先调用 Lock ,再调用 Unlock 报错:fatal error: concurrent map iteration and map write 翻译:并发map迭代 和 map 写 对应代码:range m 和 m[i] = i
var m = make(map[int]int)
func mp() {
for i := 0; i < 1000; i++ {
go func() {
//注意先调用的Unlock后调用的 Lock
defer l.Unlock()
l.Lock()
m[i] = i
}()
}
for _, v := range m {
//循环打印 map的所有值
fmt.Println(v)
}
}
//Output
/** 正确 应该能遍历1000次,实际只遍历了384次
962
340
699
...
346
772
787
结束**/
//可能会 runtime error, 先调用 Lock ,再调用 Unlock fatal error: concurrent map iteration and map write 翻译:并发map迭代 和 map 写 对应代码:range m 和 m[i] = i
func mp() {
for i := 0; i < 1000; i++ {
go func() {
l.Lock()
defer l.Unlock()
m[i] = i
}()
}
for _, v := range m {
//循环打印 map的所有值
fmt.Println(v)
}
}
//不报错,但是数据不是期望的1000个
func mp() {
var wg sync.WaitGroup
for i := 0; i < 1000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
defer l.Unlock()
l.Lock()
m[i] = i
}()
}
//block 阻塞 等上面的goroutine全部完成写操作
wg.Wait()
for _, v := range m {
//循环打印 map的所有值
fmt.Println(v)
}
}
//Output: 每次运行 300多行不等
/**
575
960
203
...
669
744
结束**/
标签:count,map,++,fmt,Println,concurrent,func,go 来源: https://blog.csdn.net/MyLoveSunset7777/article/details/122460120