Go中使用sync.Map

1. 前提

Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。

2. map并发读写测试

package main

import (
    "os/signal"
    "runtime"
    "syscall"
)

func main()  {
    // 创建一个int到int的映射
    m := make(map[int]int)
    // 开启一段并发代码
    go func() {
        // 不停地对map进行写入
        for {
            m[1] = 1
        }
    }()
    // 开启一段并发代码
    go func() {
        // 不停地对map进行读取
        for {
            _ = m[1]
        }
    }()

    signal.Ignore(syscall.SIGHUP)
    runtime.Goexit()
}

运行时报错
fatal error: concurrent map read and map write

3. 接下来用并发安全的sync.Map来测试

package main

import (
    "fmt"
    "os/signal"
    "runtime"
    "sync"
    "syscall"
)

func main()  {
    // 创建一个int到int的映射
    m := sync.Map{}
    // 开启一段并发代码
    go func() {
        // 不停地对map进行写入
        for {
            m.Store(1,1)
        }
    }()
    // 开启一段并发代码
    go func() {
        // 不停地对map进行读取
        for {
            if v, ok := m.Load(1); ok{
                fmt.Println(v)
            }
        }
    }()

    signal.Ignore(syscall.SIGHUP)
    runtime.Goexit()
}

运行时会一直输出1而不会报错

4. sync.Map基本操作

4.1 创建

直接声明,不需要make
var m sync.Map

4.2 插入、修改

  • 如果key不存在,插入value;
  • 如果key存在则修改其值
m.Store(key,value)

4.3 插入或查找

  • 如果key不存在,插入value,返回插入value的值,ok为false
  • 如果key存在,返回原map中value的值,ok为true
value,ok := m.LoadOrStore(key,value)

4.4 删除

m.Delete(key)

4.5 查找

v,ok := m.Load(key)

4.6 遍历

m.Range(func(k, v interface{}) bool {
  fmt.Println("interate:",k,v)
  return true
})
0%