Go中的Map并发访问方案 | 青训营笔记

93 阅读2分钟

0 前言

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
在大项目的实现过程中,需要用到map结构体进行快速的数据查询,但是经过查询发现,golang中的原生map结构体是不支持并发访问的,即在有多个协程进行访问时可能会出现数据错误,于是我去查找了有关资料,发现主要是有以下两种方案:

  1. map + RWMutex
  2. sync.Map

1 map加锁方案

这个方案比较好理解,既然多个协程同时对map进行写入可能发生数据的错误,那么即通过增加读写锁的方式去限制不同协程的写入操作,从而做到使不同协程在对map进行数据写入时不会发生互相的冲突,而且对于读取数据也不会有非常大的影响,只是在使用map的前后需要增加一些关于读写锁的操作,增加了一些使用成本。

2 sync.Map方案

sync.Map主要是针对多核高并发读取的场景进行了优化,在使用上sync.Map使用 Load、Delete、Store 来对数据进行操作,相对来说使用上会更加简便,但是另一方面,由于sync.Map的API中,key和value都是interface类型(在go中interface可以是任意类型),这意味着我们会失去类型检查提供的安全性。
当然我们可以通过对sync.Map再进行一层封装解决,使得其中的key和value固定为我们期望的值,这样可以省去我们反复进行类型的检查(值得注意的是,资料中的文章发布时Go的泛型还没有落实,但现在Go也有自己的泛型了)

3 两种方案如何进行选择

关于两种方案性能的测试比较
结论:

  1. sync.Map主要是针对大量的读以及少量写的场景进行的优化,在元素的读取和删除上有着更好的性能
  2. 如果有较多的写入操作,则sync.Map的性能可能远远不如map加锁的方案