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

下面来看下并发情况下读写 map 时会出现的问题,代码如下:

package mainfunc 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 内部会对这种并发操作进行检查并提前发现。

需要并发读写时,一般的做法是加锁,但这样性能并不高。Go 语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map。sync.Map 和 map 不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构。

sync.Map有以下特性:

  • 无须初始化,直接声明即可。
  • sync.Map 不能使用 map 的方式进行取值和设置等操作,而是使用 sync.Map 的方法进行调用。Store 表示存储,Load 表示获取,Delete 表示删除。
  • 使用 Range 配合一个回调函数进行遍历操作,通过回调函数返回内部遍历出来的值。Range 参数中的回调函数的返回值功能是:需要继续迭代遍历时,返回 true;终止迭代遍历时,返回 false。
package mainimport ("fmt""sync"
)func main() {var scene sync.Map// 将键值对保存到sync.Mapscene.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

代码说明如下:

  • 第 10 行,声明 scene,类型为 sync.Map。注意,sync.Map 不能使用 make 创建。
  • 第 13~15 行,将一系列键值对保存到 sync.Map 中,sync.Map 将键和值以 interface{} 类型进行保存。
  • 第 18 行,提供一个 sync.Map 的键给 scene.Load() 方法后将查询到键对应的值返回。
  • 第 21 行,sync.Map 的 Delete 可以使用指定的键将对应的键值对删除。
  • 第 24 行,Range() 方法可以遍历 sync.Map,遍历需要提供一个匿名函数,参数为 k、v,类型为 interface{},每次 Range() 在遍历一个元素时,都会调用这个匿名函数把结果返回。

sync.Map 没有提供获取 map 数量的方法,替代方法是获取时遍历自行计算数量。sync.Map 为了保证并发安全有一些性能损失,因此在非并发情况下,使用 map 相比使用 sync.Map 会有更好的性能。

golang中的sync.Map相关推荐

  1. golang中并发sync和channel

    golang中并发sync和channel chenbaoke · 2014-12-08 13:00:01 · 19151 次点击 · 预计阅读时间 5 分钟 · 不到1分钟之前 开始浏览 这是一个创 ...

  2. golang中的sync.WaitGroup

    golang中的sync.WaitGroup Posted on 2015/04/09刚才看golang的sync的包,看见一个很有用的功能.就是WaitGroup. 先说说WaitGroup的用途: ...

  3. golang中的sync.once

    sync.Once.Do(f func())是一个挺有趣的东西,能保证once只执行一次,无论你是否更换once.Do(xx)这里的方法,这个sync.Once块只会执行一次 与sync.WaitGr ...

  4. Golang sync.Map 原理(两个map实现 读写分离、适用读多写少场景)

    参考: 由浅入深聊聊Golang的sync.Map 通过对源码的逐行分析,清晰易懂 Golang sync.Map原理 通过向 sync.Map 中增删改查来介绍sync.Map的底层原理 Golan ...

  5. golang 中 map 转 struct

    golang 中 map 转 struct package mainimport ("fmt""github.com/goinggo/mapstructure" ...

  6. golang sync.Map 使用

    自1.9版本以后提供了sync.Map,支持多线程并发读写,比之前的加锁map性能要好一点. 提供一下几个方法: type Map//删除指定keyfunc (m *Map) Delete(key i ...

  7. c语言map函数k v都是int,Go语言sync.Map(在并发环境中使用的map)

    Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的. 下面来看下并发情况下读写 map 时会出现的问题,代码如下: // 创建一个int到int的映射 m := make(m ...

  8. golang中的atomic,以及CAS操作

    CAS无锁算法 要实现无锁(lock-free)的非阻塞算法有多种实现方法,其中CAS(比较与交换,Compare and swap)是一种有名的无锁算法.CAS是CPU指令,在大多数处理器架构,包括 ...

  9. 记一次golang中sync.Map并发创建、读取的问题

    记一次golang中sync.Map并发创建.读取的问题  cunfate https://www.jianshu.com/p/f472e79909bc 背景: 我们有一个用go做的项目,其中用到了z ...

最新文章

  1. 趣图:老手调试多线程,666
  2. JavaSE基础知识(5)—面向对象(5.2类的成员)
  3. 因式分解,算术基本定理,积性函数(POJ 1452 Happy2004)
  4. 「Algospot」津巴布韦ZIMBABWE
  5. java keygenerator_Java密码学KeyGenerator类
  6. 图片抓取_小小爬虫批量抓取微信推文里的图片
  7. 软考信息系统项目管理师_管理科学(运筹学)2---软考高级之信息系统项目管理师034
  8. java map size 不准确_java1.7以前ConcurrentHashMap的size方法
  9. 商业数据库之死:Oracle 的困境
  10. mysql打开数据库命令_MySQL操作数据库指令
  11. 大数据学习相关内容总结
  12. java 查看类_JAVA基础知识之JVM-——通过反射查看类信息
  13. Xilinx 7系列FPGA收发器架构之硬件设计指导(一)
  14. [RK3588-Android12] Uboot-Logo引起的 HDMI第一次开机无声音问题
  15. 云计算大数据学习中心作业2
  16. 利用 Global mapper制作地图瓦片
  17. java电子邮件收发系统,基于Java_Mail的电子邮件收发系统毕业设计
  18. 【数据结构与算法基础】AOE网络与关键路径
  19. Cookie-网站登录-下次自动登录
  20. 输出自己的姓名python_【Python编程:显示自己的的姓名和学号,并将学号各位数字相加求和,并显示.】...

热门文章

  1. 【Netty】Netty 核心组件 ( Pipeline | ChannelPipeline )
  2. 【Android 系统开发】 Android 系统启动流程简介
  3. 提升vector性能的几个技巧
  4. 【刷题记录】杂题记录
  5. 全国计算机技术与软件专业技术资格(水平)考试【软件评测师】-考试内容总结(四)中间件基础知识...
  6. PYTHON调用JENKINS的API来进行CI
  7. moveit!功能包安装问题
  8. PostgreSQL 当有多个索引可选时,优化器如何选择
  9. Vue.js 插件开发详解
  10. 5 个关于 API 中日期和时间设计规则