go map并发安全问题,如何解决

题目来源

答案1:(树枝)

go map 并发为什么不是安全的?

熟悉Go语言的人或多或少都听过Rob Pike的这句话 Do not communicate by sharing memory; instead, share memory by communicating.这句话的意思是:不要以共享内存的方式来通讯,相反,要经过通讯来共享内存这也很好的解释了为什么Go不把map设计为并发安全的。

但是在生产环境中遇到需要对map大量的并发写入与读取,如何保证map的并发安全呢?

  1. func main() {
  2. testMap := make(map[int]int)
  3. for i := 0; i < 100; i++ {
  4. go func(i int) {
  5. testMap[i+1] = i
  6. }(i)
  7. }
  8. for i := 0; i < 100; i++ {
  9. go func(i int) {
  10. fmt.Println("对map取值:",testMap[i+1])
  11. }(i)
  12. }
  13. time.Sleep(time.Second)
  14. }

直接对map进行并发读写会painc:concurrent map writes

保证map并发安全的两种方法

  1. 使用读写锁
  1. func main() {
  2. var lock sync.RWMutex
  3. testMap := make(map[int]int)
  4. for i := 0; i < 100; i++ {
  5. go func(i int) {
  6. lock.Lock()
  7. testMap[i+1] = i
  8. lock.Unlock()
  9. }(i)
  10. }
  11. for i := 0; i < 100; i++ {
  12. go func(i int) {
  13. lock.RLock()
  14. fmt.Println("对map取值:",testMap[i+1])
  15. lock.RUnlock()
  16. }(i)
  17. }
  18. time.Sleep(time.Second)
  19. }
  1. 使用sync.Map
    1. func main() {
    2. var m sync.Map
    3. for i := 0; i < 100; i++ {
    4. go func(i int) {
    5. m.Store(i+1, i)
    6. }(i)
    7. }
    8. for i := 0; i < 100; i++ {
    9. go func(i int) {
    10. v, _ := m.Load(i + 1)
    11. fmt.Printf("使用map的key:%d,取到map的value:%d", i+1, v)
    12. }(i + 1)
    13. }
    14. }
    15. time.Sleep(time.Second)