go在并发情况下使用map

 

两种方式解决并发访问map

  • 读写锁实现并发安全Map
  • sync.Map

 

读写锁实现并发安全Map

并发访问map是不安全的。
所以如果希望在多协程中并发访问map,必须提供某种同步机制,一般情况下通过读写锁sync.RWMutex实现对map的并发访问控制,将map和sync.RWMutex封装一下,可以实现对map的安全并发访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main
 
import (
    "fmt"
    "sync"
)
// M
type M struct {
    Map    map[interface{}]interface{}
    lock *sync.RWMutex
}
// Set ...
func (m *M) Set(key interface{}, value interface{}) {
    m.lock.RLock()
    defer m.lock.RUnlock()
    m.Map[key] = value
}
// Get ...
func (m *M) Get(key interface{}) interface{} {
    m.lock.Lock()
    defer m.lock.Unlock()
    return m.Map[key]
}
 
 
 
func main() {
    Map := &M{
        make(map[interface{}]interface{}),
        new(sync.RWMutex),
    }
 
    Map.Set(2,"2323")
    Map.Set("hello",343)
    fmt.Println(Map.Get(2))
    fmt.Println(Map.Get("hello"))
}

 

sync.Map

go1.9之后加入了支持并发安全的Map sync.Map。

sync.Map 通过一份只使用原子操作的数据和一份冗余了只读数据的加锁数据实现一定程度上的读写分离,使得大多数读操作和更新操作是原子操作,写入新数据才加锁的方式来提升性能。
1、Store 存 key,value

2、LoadOrStore 取&存

3、Load 取key对应的value

4、Range 遍历所有的key,value

5、Delete 删除key,及其value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main
  
import (
    "fmt"
    "sync"
)
  
func main() {
    var m sync.Map
  
    //Store
    m.Store(1,"a")
    m.Store(2,"b")
  
    //LoadOrStore
    //若key不存在,则存入key和value,返回false和输入的value
    v,ok := m.LoadOrStore("1","aaa")
    fmt.Println(ok,v) //false aaa
  
    //若key已存在,则返回true和key对应的value,不会修改原来的value
    v,ok = m.LoadOrStore(1,"aaa")
    fmt.Println(ok,v) //false aaa
  
    //Load
    v,ok = m.Load(1)
    if ok{
        fmt.Println("it's an existing key,value is ",v)
    } else {
        fmt.Println("it's an unknown key")
    }
  
    //Range
    //遍历sync.Map, 要求输入一个func作为参数
    f := func(k, v interface{}) bool {
        //这个函数的入参、出参的类型都已经固定,不能修改
        //可以在函数体内编写自己的代码,调用map中的k,v
  
            fmt.Println(k,v)
            return true
        }
    m.Range(f)
  
    //Delete
    m.Delete(1)
    fmt.Println(m.Load(1))
  
}

 

refer:

sync.Map vs Map with lock

Go 1.9 sync.Map揭秘

golang 并发安全Map以及分段锁的实现

posted @   -零  阅读(2600)  评论(1编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
历史上的今天:
2019-02-21 数据库学习之事务
2019-02-21 pymysql的使用
2019-02-21 pymysql:Mysql拒绝从远程访问的解决办法
点击右上角即可分享
微信分享提示