-
Map的知识点
- Map是无序的,所以每次遍历的顺序随机
- 原生的Map不支持并发读写
- Map中 Key 必须要是被比较类型 Value 可以是任意类型
不可被比较的 : slice、map 、 func - Map的底层结构是HSMap
-
Map的并发操作
- 测试Map是否并发
func main() { test := map[int]string{1: "test"} go func() { for { test[1] = "test" } }() go func() { for { test[1] = "test" } }() for { } fmt.Println(test) }返回数据:
fatal error: concurrent map writes- 解决方案1 : Map中加锁
var s sync.RWMutex var Test = map[int]string{1: "test"} func main() { for i := 0; i < 50; i++ { go test() } time.Sleep(5 * time.Second) } func test() { // var s sync.RWMutex // 锁加载函数里面会出现下面的错误 // fatal error: concurrent map iteration and map write go func() { for { s.Lock() Test[1] = "test1" s.Unlock() } }() go func() { for { s.Lock() Test[1] = "test2" s.Unlock() } }() time.Sleep(time.Second) fmt.Printf("%v %p\n", test, test) }返回数据
map[1:test1] map[1:test2]随机出现优点: 实现简单粗暴,好理解
缺点: 锁的粒度为整个Map,存在优化的空间
适用场景: all- 解决方案2 :
var s sync.Map func main() { s.Store(1, 1) for i := 0; i < 50; i++ { go test() } time.Sleep(5 * time.Second) } func test() { go func() { for { s.Store(1, 2) } }() go func() { for { s.Store(1, 3) } }() time.Sleep(time.Second) fmt.Println(s.Load(1)) }返回结果:
2 true 3 true优点:官方出品;空间换时间;读写分离
缺点:不适用大量写的场景,这样会导致read Map读不到数据,而进一步加
锁读取,同时dirty Map也会一直晋升为read Map,整体性较差
适用场景: 大量读,少量写优化方向: 把锁的粒度尽可能降低来提高运行速度
实现 -
面试题
【中级】关于map,下面说法正确的是() A. map反序列化时json.unmarshal的入参必须为map的地址 B. 在函数调用中传递map,则子函数中对map元素的增加不会导致父函数中map的修改 C. 在函数调用中传递map,则子函数中对map元素的修改不会导致父函数中map的修改 D. 不能使用内置函数delete删除map的元素 参考答案:A 【初级】使用map不需要引入任何库() 参考答案:T
Golang从入门到放弃200618--Map(3)Map的并发
最新推荐文章于 2024-01-28 10:30:00 发布
本文深入讨论了Golang中Map的并发问题,指出原生Map不支持并发读写,并强调Key必须是可比较类型。文章提到了并发操作可能导致的性能瓶颈,并分析了两种并发控制策略的优缺点:官方的读写分离方案以及在Map中加锁。同时,提出了通过降低锁粒度以优化并发性能的思路,并给出了测试Map并发的面试题。
1464

被折叠的 条评论
为什么被折叠?



