269_尚硅谷_全局互斥锁解决资源竞争

1.channel管道-----基本介绍1.channel管道-----基本介绍

2.全局变量加锁同步,互斥锁_代码2.全局变量加锁同步,互斥锁_代码

package main

import (
	"fmt"
	"math/big" // todo 如果不用该包中的big.Int方法,数据会有溢出,输出为0
	"sync"     // todo 互斥锁
	"time"
)

// * 需求: 要计算 1-200 的各个数的阶乘, 并且把各个数的阶乘放入到map中。最后显示出来。要求使用 goroutine 完成

// * 思路
//     1. 编写一个函数,计算各个数的阶乘,并放入到全局map中
//     2. 启动的协程是多个, 统计的将结果放入 map中
//     3. map 应该做出一个全局的

var (
	// todo math/big 使用
	myMap = make(map[int]*big.Int)
	// ! new: 添加互斥锁
	lock sync.Mutex
)

// test()函数就是计算n!(n的阶乘), 让将这个结果放入到 myMap中
func test(n int) {
	// todo math/big包的使用
	res := big.NewInt(1)
	for i := 1; i <= n; i++ {
		// res *= i
		// todo math/big使用
		res.Mul(res, big.NewInt(int64(i)))
	}
	// 将res 结果放入 myMapp

	// ! 【问题1】: fatal error: concurrent map writes, 因为没加锁,同时操作map导致的
	// * 解决: 添加锁的机制
	// ! new: 加锁保护 map 写入
	lock.Lock()
	myMap[n] = res
	lock.Unlock()
}

func main() {
	// 开启多个协程执行该任务, 启了200个协程
	for i := 1; i <= 200; i++ {
		// ! new: 添加 200 次
		go test(i)
	}

	// ! new: 等待所有协程完成
	// wg.Wait()

	// ! 【问题2】: main函数执行结束后,则main中调用的协程直接终止,休眠10秒
	// * 解决: 执行go build -race name.go 运行.exe程序解决
	time.Sleep(time.Second * 10)
	// ! new: 读取结果时,再次加锁
	lock.Lock()
	// 输出结果, 遍历该结果
	for i, v := range myMap {
		fmt.Printf("map[%d]= %d\n", i, v)
	}
	lock.Unlock()
}

3.全局变量加锁同步,互斥锁_运行结果3.全局变量加锁同步,互斥锁_运行结果

posted on 2026-03-03 20:00  与太阳肩并肩  阅读(0)  评论(0)    收藏  举报

导航