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)
88 8
|
25天前
|
存储 安全 Go
Go语言中的map数据结构是如何实现的?
Go 语言中的 `map` 是基于哈希表实现的键值对数据结构,支持快速查找、插入和删除操作。其原理涉及哈希函数、桶(Bucket)、动态扩容和哈希冲突处理等关键机制,平均时间复杂度为 O(1)。为了确保线程安全,Go 提供了 `sync.Map` 类型,通过分段锁实现并发访问的安全性。示例代码展示了如何使用自定义结构体和切片模拟 `map` 功能,以及如何使用 `sync.Map` 进行线程安全的操作。
|
2月前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
65 12
|
3月前
|
存储 Go
go语言 遍历映射(map)
go语言 遍历映射(map)
56 2
|
4月前
|
存储 安全 Java
Map的并发处理,助你提升编程效率,代码更优雅高效。
【10月更文挑战第19天】Map使用技巧大公开:从选择合适的Map实现(如HashMap、TreeMap、LinkedHashMap)到利用Map的初始化、使用Map.Entry遍历、运用computeIfAbsent和computeIfPresent方法,再到Map的并发处理,助你提升编程效率,代码更优雅高效。
48 2
|
5月前
|
Go 定位技术 索引
Go 语言Map(集合) | 19
Go 语言Map(集合) | 19
|
6月前
|
存储 算法 Java
Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据
Go 通过 Map/Filter/ForEach 等流式 API 高效处理数据
|
6月前
|
存储 安全 NoSQL
Go map 读写性能优化 - 分片 map
Go map 读写性能优化 - 分片 map
59 1
|
6月前
|
存储 人工智能 安全
go sync.Map 设计与实现
go sync.Map 设计与实现
44 1
|
6月前
|
存储 缓存 Go
如何检查 Go map 是否包含某个键?
【8月更文挑战第31天】
78 0