8.2 Go 锁
2024-09-07 13:48:07
8.2 Go 锁
案例(坑):多个goroutine操作同一个map。
go提供了一种叫map的数据结构,可以翻译成映射,对应于其他语言的字典、哈希表。借助map,可以定义一个键和值,然后可以从map中获取、设置和删除这个值,尤其适合数据查找的场景。
但是map的使用有一定的限制,如果是在单个协程中读写map,那么不会存在什么问题,如果是多个协程并发访问一个map
,有可能会导致程序退出,并打印下面错误信息。
fatal error: concurrent map writes
错误案例代码
package main var myMap = make(map[int]int, 10) //要求计算50的阶乘结果
//阶乘就是1*2*3*4...50 =? func test(n int) {
//定义初始值1
res := 1
//每次循环进行阶乘
for i := 0; i <= n; i++ {
res *= i
}
//最终计算结果,写入map
//由于多个协程同时操作map,引发资源竞争报错
myMap[n] = res }
func main() {
//开启50个协程
for i := 0; i < 10; i++ {
go test(10)
}
}
并发访问map是不安全的操作,在协程
中访问map,必须提供某种同步资源
机制,使用sync.Mutex
互斥锁同步解决协程的竞争问题。
package main import (
"fmt"
"sync"
"time"
) var lock sync.Mutex func Printer(str string) {
//我现在开始使用打印机了,其他人都等我完事了再来
lock.Lock()
for _, data := range str {
fmt.Printf("%c", data)
time.Sleep(time.Second)
}
//我完事了,你们上吧
lock.Unlock()
fmt.Printf("\n")
} func Alex() {
Printer("hello")
}
func Wupeiqi() {
Printer("oldboy")
} func main() {
//coffe(10)//单线程执行函数
go Alex()
go Wupeiqi()
//主线程等待协程结束后 再退出
time.Sleep(time.Second * 10)
}
结论:
1.可以使用加锁的方式解决goroutine的通讯。
2.主线程等待所有goroutine的时间难以确定,设置固定的等待时间肯定不合理。
3.对全局变量加锁同步来通讯,也不利于多个协程对变量的读写。
4.要让主线程等待所有goroutine退出后在退出,如何知道所有goroutine都退出了呢?
5.因此,channel应运而生!!
最新文章
- 小丁带你走进git的世界三-撤销修改
- jquery-创建弹出框原理
- 使用Roboguice依赖注入规划Android项目
- CSS两列高度自适应,右边自适应
- Navicat连接oracle,出现Only compatible with oci version 8.1 and&;nb (转)
- dbcp2和dbcp 1.4在API层面的差异
- Matlab最短路径问题记录
- struts2 标签 --<;<;s:url >;
- 夺命雷公狗ThinkPHP项目之----企业网站19之网站配置信息的修改
- 向Array中添加希尔排序
- 2026-Keroro侵略地球
- 通过 PHP 判断用户的设备是否是移动设备
- 4418SPI2对应管脚位置
- 编译gd-2.0.35.tar.gz时报错:gd_png.c:16:53: error: png.h: No such file or directory
- 【译】ASP.NET MVC 5 教程 - 10:添加验证
- 递归——CPS(三)
- svg笔记----------path篇
- Oracle 生成一张测试表并插入随机数据
- [cf453e]Little Pony and Lord Tirek
- ES6躬行记(5)——对象字面量的扩展