268_尚硅谷_协程并发(并行)资源竞争问题
1.channel(管道)-----需求
2.要计算 1-200 的各个数的阶乘, 并且把各个数的阶乘放入到map中。最后显示出来。要求使用 goroutine 完成_方案2代码
package main
import (
"fmt"
"math/big" // todo 如果不用该包中的big.Int方法,数据会有溢出,输出为0
"sync"
)
// * 需求: 要计算 1-200 的各个数的阶乘, 并且把各个数的阶乘放入到map中。最后显示出来。要求使用 goroutine 完成
// * 思路
// 1. 编写一个函数,计算各个数的阶乘,并放入到全局map中
// 2. 启动的协程是多个, 统计的将结果放入 map中
// 3. map 应该做出一个全局的
var (
// todo math/big 使用
myMap = make(map[int]*big.Int)
// ! new: 添加互斥锁
mu sync.Mutex
// ! 添加 WaitGroup 等待所有协程完成
wg sync.WaitGroup
)
// test()函数就是计算n!(n的阶乘), 让将这个结果放入到 myMap中
func test(n int) {
// ! new: 协程结束时通知 WaitGroup
defer wg.Done()
// 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 写入
mu.Lock()
myMap[n] = res
mu.Unlock()
}
func main() {
// 开启多个协程执行该任务, 启了200个协程
for i := 1; i <= 200; i++ {
// ! new: 添加 200 次
wg.Add(1)
go test(i)
}
// ! 【问题2】: main函数执行结束后,则main中调用的协程直接终止,休眠10秒
// * 解决: 执行go build -race name.go 运行.exe程序解决
// time.Sleep(time.Second * 10)
// ! new: 等待所有协程完成
wg.Wait()
// 输出结果, 遍历该结果
for i, v := range myMap {
fmt.Printf("map[%d]= %d\n", i, v)
}
}
3.要计算 1-200 的各个数的阶乘, 并且把各个数的阶乘放入到map中。最后显示出来。要求使用 goroutine 完成_方案2运行结果
4.同时操作map的示意图,会直接运行会导致报错,需要有锁机制处理或者编译执行-race(资源竞争处理)
浙公网安备 33010602011771号