golang - sync.Map

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

// 创建一个int到int的映射
m := make(map[int]int)

// 开启一段并发代码
go func() {

    // 不停地对map进行写入
    for {
        m[1] = 1
    }

}()

// 开启一段并发代码
go func() {

    // 不停地对map进行读取
    for {
        _ = m[1]
    }

}()

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

}

运行代码会报错:

fatal error: concurrent map read and map write

错误信息显示,并发的 map 读和 map 写,也就是说使用了两个并发函数不断地对 map 进行读和写而发生了竞态问题,map 内部会对这种并发操作进行检查并提前发现。因此需要在并发情况下使用map,就需要用到今天的主角——sync.Map

特性
  • 无须初始化,直接声明即可
  • sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用,Store 表示存储,Load 表示获取,Delete 表示删除
  • 使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值,Range 参数中回调函数的返回值在需要继续迭代遍历时,返回 true,终止迭代遍历时,返回 false
    并发安全的sync.Map演示代码如下:
package main

import (
      "fmt"
      "sync"
)

func main() {

    var scene sync.Map

    // 将键值对保存到sync.Map
    scene.Store("greece", 97)
    scene.Store("london", 100)
    scene.Store("egypt", 200)

    // 从sync.Map中根据键取值
    fmt.Println(scene.Load("london"))

    // 根据键删除对应的键值对
    scene.Delete("london")

    // 遍历所有sync.Map中的键值对
    scene.Range(func(k, v interface{}) bool {

        fmt.Println("iterate:", k, v)
        return true
    })

}

代码输出如下:

100 true
iterate: egypt 200
iterate: greece 97

代码说明如下:

  • sync.Map不能使用make创建
  • 将键值对存到sync.Map中时,sync.Map将键和值以interface{}类型进行保存
  • 提供一个sync.Map的键给Load方法后将查询到键对应的值

你可能感兴趣的:(Go,golang,开发语言)