主线程,协程和互斥锁
package main
//路径上加上包的唯一标识 demo14,线程和协程,是go的核心
import (
"fmt"
"time"
"sync"
)
// 需求:计算1-200之间所有数的阶乘,并且把各个数的阶乘放入map中。最后显示出来。使用协程完成。
var (
map1 = make(map[int]int, 10) // 声明一个全局map
lock sync.Mutex //互斥锁
)
func main() {
for i := 1; i <= 200; i++ {
// 启动200个协程
go test(i)
}
//问题1 主线程休眠10秒钟,不休眠的话,因为主线程结束,协程也会结束,但是休眠的时间不确定
time.Sleep(time.Second * 10)
lock.Lock() // 读加锁 读的时候,可能会出现竞争,因为主线程不知道10秒钟协程是否执行完成;加锁可以避免这个问题
for i, v := range map1 {
fmt.Printf("map[%d]=%d\n", i, v)
}
lock.Unlock() // 读解锁
}
func test(n int){
// 计算阶乘的函数
res := 1
for i := 1; i <= n; i++ {
res = res * i
}
// 问题2,如果多个线程同时尝试写同一个数据结构(如Map),就可能发生数据竞争、数据不一致或其他并发问题
lock.Lock() // 写,加锁
map1[n] = res
lock.Unlock() //写完,解锁
}
go build -race ./main.go之后执行main.exe,可以检查是否存在竞争问题