go并发访问map的坑 fatal error: concurrent map read and map write

简介: go并发访问map的坑 fatal error: concurrent map read and map write

前言


go 并发访问map是不安全的, 会出现未定义的错误导致程序退出…坑总得踩一踩才会知道


例子


先写一个错误的

package main
import "fmt"
func test() map[string]interface{}{
  taskList := []string{"a", "b"}
  result := make(map[string]interface{})
  for _, task := range taskList {
    go func(task string) {
      switch task {
      case "a":
        result["a"] = "xiaofei"
      case "b":
        result["b"] = "ceshi"
      }
    }(task)
  }
  return result
}
func main() {
  for a := 0; a < 1000; a++ {
    fmt.Println(test())
  }
}

返回结果

image.png


上面代码有两个问题, 第一个是没有阻塞go程, 第二个就是并发访问map了


正确的写法

package main
import (
  "fmt"
  "sync"
)
// 使用读写锁 sync.RWMutex
type NewMap struct {
  lock *sync.RWMutex
  sm   map[interface{}]interface{}
}
func (m *NewMap) Set(k interface{}, v interface{}) bool {
  m.lock.Lock()
  defer m.lock.Unlock()
  m.sm[k] = v
  return true
}
func test() map[interface{}]interface{} {
  taskList := []string{"a", "b"}
  xf := &sync.WaitGroup{}
  result := NewMap{
    lock: new(sync.RWMutex),
    sm: make(map[interface{}]interface{}),
  }
  for _, task := range taskList {
    xf.Add(1)
    go func(task string) {
      defer xf.Done()
      switch task {
      case "a":
        result.Set("a", "xiaofei")
      case "b":
        result.Set("b", "ceshi")
      }
    }(task)
  }
  xf.Wait()
  return result.sm
}
func main() {
  for a := 0; a < 100; a++ {
    fmt.Println(test())
  }
}

建议把这个map做一个基类方法, 所有的方法封装一下直接用就ok了;

目录
相关文章
|
3月前
|
Go
Go 语言为什么不支持并发读写 map?
Go 语言为什么不支持并发读写 map?
|
14天前
|
存储 安全 Java
Map的并发处理,助你提升编程效率,代码更优雅高效。
【10月更文挑战第19天】Map使用技巧大公开:从选择合适的Map实现(如HashMap、TreeMap、LinkedHashMap)到利用Map的初始化、使用Map.Entry遍历、运用computeIfAbsent和computeIfPresent方法,再到Map的并发处理,助你提升编程效率,代码更优雅高效。
22 2
|
2月前
|
Go 定位技术 索引
Go 语言Map(集合) | 19
Go 语言Map(集合) | 19
|
3月前
|
存储 算法 Java
Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据
Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据
|
3月前
|
存储 安全 NoSQL
Go map 读写性能优化 - 分片 map
Go map 读写性能优化 - 分片 map
44 1
|
3月前
|
存储 人工智能 安全
go sync.Map 设计与实现
go sync.Map 设计与实现
33 1
|
3月前
|
存储 缓存 Go
如何检查 Go map 是否包含某个键?
【8月更文挑战第31天】
23 0
|
3月前
|
存储 Go 容器
Go从入门到放弃之map(字典)
Go从入门到放弃之map(字典)
|
3月前
|
存储 Java 关系型数据库
听说过对 Go map 做 GC 吗?
听说过对 Go map 做 GC 吗?
|
3月前
|
存储 算法 Go
go map 设计与实现
go map 设计与实现
28 0