Map的特点
map 在并发情况下,只读是线程安全的,同时读写是线程不安全的
并发的 map 读和 map 写,使用了两个并发函数不断地对 map 进行读和写而发生了竞态问题,map 内部会对这种并发操作进行检查并提前发现。
示例:
package main
?
func main() {
/*声明一个Map*/
mapInt := make(map [int] int)
?
/*开启一段并发代码,不断地写入value*/
go func() {
for {
mapInt[1] = 1
}
}()
?
/*开启另一段并发代码,读取mapInt*/
go func() {
for {
_ =mapInt[1]
}
}()
?
/*输出*/
for {
?
}
}
syncMap
特点:
-
syncMap是一个包,包下面有安全操作Map的方法
-
无须初始化,直接声明即可。
-
sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除。
-
使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false。
package main
?
import (
"fmt"
"sync"
)
?
func main() {
var scene sync.Map
?
/*调用包内的方法将键值对保存进去*/
scene.Store("name", "JunkingBoy")
scene.Store("age", 22)
scene.Store("long", 18)
/*
键值对保存到 sync.Map 中,sync.Map 将键和值以 interface{} 类型进行保存。
所以可以是任意类型的value
*/
?
/*使用包内方法从键中取值*/
fmt.Println(scene.Load("long"))
?
/*删除对应的键值对*/
scene.Delete("age")
?
//遍历键值对--->调用sync包下的方法
scene.Range(func(key, value interface{}) bool {
fmt.Println("iterate", key, value)
return true
})
}
syncMap的缺点:
-
sync.Map 没有提供获取 map 数量的方法,替代方法是在获取 sync.Map 时遍历自行计算数量,sync.Map 为了保证并发安全有一些性能损失,因此在非并发情况下,使用 map 相比使用 sync.Map 会有更好的性能。
-