golang sync.Map 原理以及性能分析

2024-05-23 17:58

本文主要是介绍golang sync.Map 原理以及性能分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

sync.Map 原理以及性能分析

  • 支持并发的map
  • sync.Map
    • 数据结构
    • Load
    • Store
    • delete
    • Range
  • sync.Map总结
  • sync.Map,读写锁的适用场景
  • 参考文献

golang支持map关键字,golang的map的读写是编译成runtime的函数调用。但是默认的map是非线程安全的。go 1.9 版本中支持了 sync.Map 用于线程安全的map。

关于go map的实现可以参考:Golang map实践以及实现原理

支持并发的map

golang内置的map读写操作,很多都是编译器帮我们转换成runtime的函数调用,而且整体的设计比较封闭,没有留下扩展的空间。

要支持线程安全的map,一种方式就是在go内置的map上进行封装。比较简单的就是使用sync提供的锁来实现,这种是最简单的,具体情况这里就不说了。

sync.Map

go 1.9 官方提供了sync.Map 来优化线程安全的并发读写的map。该实现也是基于内置map关键字来实现的。

这个实现类似于一个线程安全的 map[interface{}]interface{} . 这个map的优化主要适用了以下场景:

(1)给定key的键值对只写了一次,但是读了很多次,比如在只增长的缓存中;
(2)当多个goroutine读取、写入和覆盖的key值不相交时。

在这两种情况下,使用Map可能比使用单独互斥锁或RWMutex的Go Map大大减少锁争用。

对于其余情况最好还是使用RWMutex保证线程安全。

数据结构

先看一下底层的数据结构:

// 封装的线程安全的map
type Map struct {// lockmu Mutex// 实际是readOnly这个结构// 一个只读的数据结构,因为只读,所以不会有读写冲突。// readOnly包含了map的一部分数据,用于并发安全的访问。(冗余,内存换性能)// 访问这一部分不需要锁。read atomic.Value // readOnly// dirty数据包含当前的map包含的entries,它包含最新的entries(包括read中未删除的数据,虽有冗余,但是提升dirty字段为read的时候非常快,不用一个一个的复制,而是直接将这个数据结构作为read字段的一部分),有些数据还可能没有移动到read字段中。// 对于dirty的操作需要加锁,因为对它的操作可能会有读写竞争。// 当dirty为空的时候, 比如初始化或者刚提升完,下一次的写操作会复制read字段中未删除的数据到这个数据中。dirty map[interface{}]*entry// 当从Map中读取entry的时候,如果read中不包含这个entry,会尝试从dirty中读取,这个时候会将misses加一,// 当misses累积到 dirty的长度的时候, 就会将dirty提升为read,避免从dirty中miss太多次。因为操作dirty需要加锁。misses int
}// readOnly is an immutable struct stored atomically in the Map.read field.
type readOnly struct {m       map[interface{}]*entry// 如果Map.dirty有些数据不在m中,这个值为trueamended bool 
}// An entry is a slot in the map corresponding to a particular key.
type entry struct {// *interface{}p unsafe.Pointer 
}

readOnly.amended指明Map.dirty中有readOnly.m未包含的数据,所以如果从Map.read找不到数据的话,还要进一步到Map.dirty中查找。

这里虽然有冗余的两份map数据,但是Map.dirtyreadOnly.m的value都是一个指针变量 *entry,所以整体内存占用还好。

sync.Map 的kv都是 interface{} ,entry里面的p实际是一个 *interface{},也就是entry实际保存的是指向value的指针。

这里p有三个值:

  1. nil: entry已被删除了,并且m.dirty为nil
  2. expunged: entry已被删除了,并且m.dirty不为nil,而且这个entry不存在于m.dirty中
  3. 其它: entry是一个正常的value

sync.Map也是在golang提供的map关键字之上封装实现的。

sync.Map 整体的优化可以描述为以下几点:

  1. 空间换时间。 通过冗余的两个数据结构(read、dirty),实现加锁对性能的影响。
  2. map只保存key和对应的value的指针,这样可以并发的读写map, 实际更新指向value的指针再通过基于CAS的无锁atomic。
  3. 使用只读数据(read),避免读写冲突
  4. 动态调整,miss次数多了之后,将dirty数据提升为read。
  5. double-checking。
  6. 延迟删除。 删除一个键值只是打标记,只有在提升dirty的时候才清理删除的数据。
  7. 优先从read读取、更新、删除,因为对read的读取不需要锁。

Load

线程安全的加载key对应的value:

func (m *Map) Load(key interface{}) (value interface{}, ok bool) {// 1.首先从m.read中加载只读的readOnly, 从它的map中查找,无锁。read, _ := m.read.Load().(readOnly)e, ok := read.m[key]// 2. 如果没找到,并且m.dirty中有新数据,需要从m.dirty查找,这个时候需要加锁if !ok && read.amended 

这篇关于golang sync.Map 原理以及性能分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/996322

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

性能测试介绍

性能测试是一种测试方法,旨在评估系统、应用程序或组件在现实场景中的性能表现和可靠性。它通常用于衡量系统在不同负载条件下的响应时间、吞吐量、资源利用率、稳定性和可扩展性等关键指标。 为什么要进行性能测试 通过性能测试,可以确定系统是否能够满足预期的性能要求,找出性能瓶颈和潜在的问题,并进行优化和调整。 发现性能瓶颈:性能测试可以帮助发现系统的性能瓶颈,即系统在高负载或高并发情况下可能出现的问题

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

hdu4407(容斥原理)

题意:给一串数字1,2,......n,两个操作:1、修改第k个数字,2、查询区间[l,r]中与n互质的数之和。 解题思路:咱一看,像线段树,但是如果用线段树做,那么每个区间一定要记录所有的素因子,这样会超内存。然后我就做不来了。后来看了题解,原来是用容斥原理来做的。还记得这道题目吗?求区间[1,r]中与p互质的数的个数,如果不会的话就先去做那题吧。现在这题是求区间[l,r]中与n互质的数的和

黑神话,XSKY 星飞全闪单卷性能突破310万

当下,云计算仍然是企业主要的基础架构,随着关键业务的逐步虚拟化和云化,对于块存储的性能要求也日益提高。企业对于低延迟、高稳定性的存储解决方案的需求日益迫切。为了满足这些日益增长的 IO 密集型应用场景,众多云服务提供商正在不断推陈出新,推出具有更低时延和更高 IOPS 性能的云硬盘产品。 8 月 22 日 2024 DTCC 大会上(第十五届中国数据库技术大会),XSKY星辰天合正式公布了基于星

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

hdu4407容斥原理

题意: 有一个元素为 1~n 的数列{An},有2种操作(1000次): 1、求某段区间 [a,b] 中与 p 互质的数的和。 2、将数列中某个位置元素的值改变。 import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.IOException;import java.io.Inpu