268_尚硅谷_协程并发(并行)资源竞争问题

1.channel(管道)-----需求1.channel(管道)-----需求

2.要计算 1-200 的各个数的阶乘, 并且把各个数的阶乘放入到map中。最后显示出来。要求使用 goroutine 完成_方案2代码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运行结果3.要计算 1-200 的各个数的阶乘, 并且把各个数的阶乘放入到map中。最后显示出来。要求使用 goroutine 完成_方案2运行结果

4.同时操作map的示意图,会直接运行会导致报错,需要有锁机制处理或者编译执行-race(资源竞争处理)4.同时操作map的示意图

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

导航