并发环境使用的 sync.Map

map 在并发下遇到的问题

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

func main() {
  m := make(map[int]int)

  // 开启一段并发代码
  go func() {
    for {
      // 不停对 map 进行写入
      m[1] = 1
    }
  }()

  // 开启一段并发代码
  go func() {
    for {
      // 不停对 map 进行读取
      _ = m[1]
    }
  }()

  // 无限循环,让并发程序在后台执行
  for {
  }
}

感谢 Go 足够聪明,运行这段代码会直接报错 fatal error: concurrent map read and map writ。两个并发函数不断地对 map 进行读和写发生了竞态问题。map 内部会对这种并发操作进行检查并提前发现。

sync.Map 的特性

需要并发读写时,一般的做法是加锁,但这样性能不高,且要自己维护锁。推荐使用 sync.Map

  • 无须初始化,直接声明即可。
  • 不能使用 map 的方法来操作,Store 表示存储,Load 表示获取,Delete 表示删除。
  • 使用 Range 配合一个回调函数进行遍,通过回调函数返回内部遍历出来的值。Range 的返回值为 bool 其代表是否要继续迭代遍历。
func main() {
  var scence sync.Map
  scence.Store("greece", 97)
  scence.Store("london", 100)
  scence.Store("egypt", 200)

  fmt.Println(scence.Load("london"))

  scence.Delete("egypt")

  scence.Range(func(k, v interface{}) bool {
    fmt.Println("iterate:", k, v)
    return true
  })
}

如果觉得我的文章对您有用,请在支付宝公益平台找个项目捐点钱。 @Victor May 2, 2019

奉献爱心