golang全局互斥锁解决资源竞争问题
一、需求
开启是个协程,计算1-10各个数的阶乘,并且把各个数的阶乘放入到map中,最后显示出来
二、代码实现
package main
import (
"fmt"
"time"
)
var myMap = make(map[int]int, 10)
func test(n int) {
res := 1
for i := 2; i <= n; i++ {
res *= i
}
myMap[n] = res
}
func main() {
for i := 1; i <= 20; i++ {
go test(i)
}
time.Sleep(10 * time.Second)
for key, value := range myMap {
fmt.Printf("%d的阶乘为%d\n", key, value)
}
}
输出结果:
fatal error: concurrent map writes
fatal error: concurrent map writes
分析:
因为可能存在同一时间有多个协程同时操作map,这就是资源竞争问题
三、-race参数
在运行某个程序时,如何知道是否存在资源竞争问题,方法很简单,在编译程序时,增加一个参数-race即可,如下图:
四、解决方案
使用全局变量加锁同步改进程序
- 因为没有对全局变量map加锁,因此会出现资源竞争问题,代码出现错误,concurrent map writes
- 解决方案,加入互斥锁
package main
import (
"fmt"
"sync"
"time"
)
var myMap = make(map[int]int, 10)
// 声明一个全局的互斥锁
// sync 是包: synchornized 同步
// Mutex : 是互斥
var lock sync.Mutex
// 计算n!,并将计算结果放入到myMap中
func test(n int) {
res := 1
for i := 2; i <= n; i++ {
res *= i
}
// 加锁
lock.Lock()
myMap[n] = res
// 解锁
lock.Unlock()
}
func main() {
// 开启多个10个协程共同工作
for i := 1; i <= 10; i++ {
go test(i)
}
time.Sleep(10 * time.Second)
lock.Lock()
for key, value := range myMap {
fmt.Printf("%d的阶乘为%d\n", key, value)
}
lock.Unlock()
}
输出结果:
5的阶乘为120
1的阶乘为1
2的阶乘为2
7的阶乘为5040
6的阶乘为720
8的阶乘为40320
9的阶乘为362880
3的阶乘为6
4的阶乘为24
10的阶乘为3628800