💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
Go语言中的map在并发情况下,只读是线程安全的,同时读写是线程不安全的。 ``` package main func main() { // 创建一个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内部会对这种并发操作进行检查并提前发现。 需要并发读写时,一般的做法是加锁,但这样性能并不高。Go语言在1.9版本中提供了一种效率较高的并发安全的sync.Map,sync.Map和map不同,不是以语言原生形态提供,而是在sync包下的特殊结构。 sync.Map有以下特性: * 无须初始化,直接声明即可; * sync.Map不能使用map方式进行取值和设置等操作,而是使用sync.Map的方法进行调用。Store表示存储,Load表示获取,Delete表示删除; * 使用Range配合一个回调函数进行遍历操作,通过回调函数内部遍历出来的值,Range参数中回调参数的返回值在需要继续迭代遍历时,返回true,终止迭代遍历时,返回false ``` pacage 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 }) } ```