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即可,如下图:
image

image

四、解决方案

使用全局变量加锁同步改进程序

  1. 因为没有对全局变量map加锁,因此会出现资源竞争问题,代码出现错误,concurrent map writes
  2. 解决方案,加入互斥锁
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
posted @ 2021-06-09 23:04  若雨蚂蚱  阅读(244)  评论(0编辑  收藏  举报