顾名思义,sync.Map也是一种map,相当于对原生map做了封装,之所以出现的原因是map不是线程并发安全的。go设计map是考虑到map同时读写的场景不多,所以设计map在进行写操作时是不允许进行其他的操作,否则会报fatal error: concurrent map read and map write错误,示例如下:
package main func main() { m := make(map[int]int) go func() { for { _ = m[1] } }() go func() { for { m[2] = 2 } }() select {} }在Go 1.9之前解决以上问题是通过加锁的方式,但会影响读写的性能和带来一些其他的问题,这里不详述
在Go1.9版本中新增 sync.Map,支持并发读写,示例如下(慎用,cpu占用较大):
package main import ( "fmt" "sync" "time" ) var m sync.Map func main() { go func() { for { m.Store(2, 2) } }() go func() { for { v, _ := m.Load(2) fmt.Println(v) } }() time.Sleep(1 * time.Second) }sync.map是以无锁操作一级缓存的方式支持并发、提高性能。 新建情况下,可能会带来较大的开销,比如:读击穿、数据刚从二级缓存同步到一级缓存后,又要新建key,数据又要反向同步一次。
参考文章: Go语言学习——sync.map源码剖析 https://studygolang.com/topics/12363 https://blog.csdn.net/u010230794/article/details/82143179 https://blog.csdn.net/jeffrey11223/article/details/79587015 https://colobu.com/2017/07/11/dive-into-sync-Map/ https://time.geekbang.org/column/article/301174 后半段