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
结束**/

上一篇:编码技巧---调试宏


下一篇:从零开发区块链应用(十)--golang协程使用