golang_并发安全: slice和map并发不安全及解决方法
2023-09-14 09:12:21 时间
golang_并发安全: slice和map并发不安全及解决方法
Grayan · 2020-07-21 15:32:48 · 1771 次点击 · 预计阅读时间 1 分钟 · 不到1分钟之前 开始浏览这是一个创建于 2020-07-21 15:32:48 的文章,其中的信息可能已经有所发展或是发生改变。
并发安全
并发安全也叫线程安全,在并发中出现了数据的丢失,称为并发不安全
map和slice都是并发不安全的
切片并发不安全
场景: 10000个协程同时添加切片
var s []int
func appendValue(i int) {
s = append(s, i)
}
func main() {
for i := 0; i < 10000; i++ { //10000个协程同时添加切片
go appendValue(i)
}
for i, v := range s { //同时打印索引和值
fmt.Println(i, ":", v)
}
}
Output:
没有到9999,说明有数据丢失
解决方法: 加锁
var s []int
var lock sync.Mutex //互斥锁
func appendValue(i int) {
lock.Lock() //加锁
s = append(s, i)
lock.Unlock() //解锁
}
func main() {
for i := 0; i < 10000; i++ {
go appendValue(i)
}
//sort.Ints(s) //给切片排序,先排完序再打印,和下面一句效果相同
time.Sleep(time.Second) //间隔1s再打印,防止一边插入数据一边打印时数据乱序
for i, v := range s {
fmt.Println(i, ":", v)
}
}
总结: slice在并发执行中不会报错,但是数据会丢失
map并发不安全
场景: 2个协程同时读和写
func main() {
m := make(map[int]int)
go func() { //开一个协程写map
for i := 0; i < 10000; i++ {
m[i] = i
}
}()
go func() { //开一个协程读map
for i := 0; i < 10000; i++ {
fmt.Println(m[i])
}
}()
//time.Sleep(time.Second * 20)
for {
;
}
}
Output:
解决方法:尽量不要做map的并发,如果用并发要加锁,保证map的操作要么读,要么写。
var lock sync.Mutex
func main() {
m:=make(map[int]int)
go func() { //开一个协程写map
for i:=0;i<10000 ;i++ {
lock.Lock() //加锁
m[i]=i
lock.Unlock() //解锁
}
}()
go func() { //开一个协程读map
for i:=0;i<10000 ;i++ {
lock.Lock() //加锁
fmt.Println(m[i])
lock.Unlock() //解锁
}
}()
time.Sleep(time.Second*20)
}
总结: map在并发执行中会直接报错
相关文章
- Node.js 工具库 BlueBird 的一些例子:map,each 和 some
- golang中的map并发读写问题: Golang 协程并发使用 Map 的正确姿势
- map转换成JSON的方法
- jsonArray转list<map>
- JavaScript Array的map方法
- java map循环遍历_遍历循环中的遍历结构可以是
- Java map转实体类_java实体类转json
- 哈理工 oj 2122 旅行(map + 最短路dij算法)
- 强大的匿名函数lambda使用方法,结合map、apply等
- map容器/multimap容器
- 使用红黑树模拟实现map和set
- 手撕AVL树、红黑树,红黑树封装map、set
- Go语言map(Go语言映射)
- Go语言sync.Map(在并发环境中使用的map)
- Java8中Map的遍历方式总结详解编程语言
- hadoop中map到reduce的过程详解大数据
- java实现map和object互转的三种方法详解编程语言
- Oracle 视图 DBA_WORKLOAD_CONNECTION_MAP 官方解释,作用,如何使用详细说明
- Oracle 视图 RESOURCE_MAP 官方解释,作用,如何使用详细说明
- 遍历Map的四种方法详解编程语言
- Java Map.equals()方法:判断Map集合是否与指定的对象相同
- Redis精准读取Map数据的窍门(redis获取map)
- MySQL中使用Map作为参数的实现方法(mysql中map做参数)
- Oracle应用Map参数的优势初探(map参数 oracle)
- 警惕Redis Map的频繁变更(redis频繁修改map)
- Oracle中Map结构的精妙运用(oracle中MAP结构)
- 探索Redis中的Map之谜(redis里查map)
- Oracle Map映射从实施到实现(oracle map映射)
- Redis脚本快速遍历Map集(redis脚本遍历map)
- Redis存储Map一次全方位试验(redis能存map吗)