sync.Map的实现原理

news/2024/9/24 10:11:52/文章来源:https://www.cnblogs.com/echo1937/p/18428503

在 Go 语言中,sync.Map 是一个并发安全的映射结构,专门用于在高并发场景下处理键值对数据。它的并发安全是通过内部实现机制来保证的,而不是依赖外部的锁机制(如 sync.Mutexsync.RWMutex)来手动保护操作。

sync.Map 并发安全的实现原理

sync.Map 采用了一种更复杂的数据结构和操作策略来实现并发安全。它的核心设计可以分为以下几个方面:

1. 读写分离机制

sync.Map 的内部结构是通过读写分离实现的,主要由两个部分组成:

  • 只读部分(read map):用于存储稳定的数据。读取操作主要从这个只读部分进行,避免锁的使用。
  • 脏数据部分(dirty map):当数据发生修改(写入、删除)时,会被移动到脏数据区域,写入的同时加锁来确保并发安全。

2. 快速读取路径

  • 无锁读取:如果数据已经存在于 read map 中(即稳定的数据),读取操作不需要加锁,这使得 sync.Map 的读操作非常高效。
  • 写时复制:当数据在 read map 中不存在时,可能存在于 dirty map 中。此时需要升级锁并从 dirty map 读取或写入数据。

3. 写入时的锁保护

  • 当需要写入(StoreDelete)时,sync.Map 会在 dirty map 中进行操作。写操作会加锁,以确保并发写入时的安全性。
  • 每次写入时,sync.Map 都会检查 read mapdirty map 之间的数据是否需要同步(比如数据量超过某个阈值时),并对脏数据部分进行清理和迁移。

4. 懒惰同步(Lazy Synchronization)

当读操作频繁时,sync.Map 会把部分脏数据逐步迁移到 read map,从而减少读操作对锁的依赖。这种延迟同步策略保证了读操作可以尽量避免锁竞争,从而提升读取性能。

5. 原子操作

sync.Map 的部分操作(如 LoadOrStoreLoadAndDelete 等)采用了原子操作。它们的实现使用了底层的原子性检查和赋值操作,确保这些操作能够在并发环境中保持一致性。

关键操作说明

  1. 读操作 (Load)

    • 首先从 read map 中读取,如果找到,直接返回。
    • 如果在 read map 中没有找到,则会尝试从 dirty map 中读取,同时可能会触发一次锁定操作。
  2. 写操作 (Store)

    • 写操作会锁定 sync.Map,以保证在并发环境下对 dirty map 的安全写入。
    • 如果脏数据变多或写入频繁,可能会触发 read map 的同步,将一些脏数据迁移到 read map
  3. 删除操作 (Delete)

    • 删除操作也会加锁,并删除 dirty map 中的数据。
  4. 批量操作 (Range)

    • Range 操作遍历 sync.Map 中的所有数据,确保在遍历期间不会发生并发冲突。

代码示例

package mainimport ("fmt""sync"
)func main() {var m sync.Map// 写入数据m.Store("foo", 42)m.Store("bar", 100)// 读取数据value, ok := m.Load("foo")if ok {fmt.Println("foo:", value)}// 删除数据m.Delete("foo")// 使用 Range 遍历所有元素m.Range(func(key, value interface{}) bool {fmt.Println(key, value)return true})
}

sync.Map 的优点

  • 读性能高:在读多写少的场景下表现非常优异,因为 read map 读取时不需要加锁,减少了锁竞争。
  • 自动并发控制sync.Map 不需要手动管理锁机制,减少了编写并发安全代码的复杂度。
  • 适合高并发场景:特别是在大量读取的情况下,sync.Map 的性能优于传统的 map + sync.RWMutex 的方案。

何时使用 sync.Map

  • 读多写少的场景:当并发访问主要是读操作,写操作较少时,sync.Map 的读写分离机制使得它具有很高的性能。
  • 需要简单并发访问:当需要并发访问 map,而且不想手动管理锁时,sync.Map 是一个非常方便的工具。

何时不使用 sync.Map

  • 写操作非常频繁sync.Map 在写操作上需要加锁,如果写操作占比很高,可能不如手动加锁的传统 map 方案效率高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/802691.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第三周作业(海报)

我所选的主题是数字。运用数字王国的标题,吸引小学生的注意。学生们可以在数字王国中探索,从低年级的认识数字开始培养起对数学的兴趣,为以后的数学学习铺垫好坚实的基础。在本张海报中,我运用了文字、图片、插画、数字这三种素材,并且插画颜色丰富、且进校园生活和数字,…

解决pyinstaller打包后的程序有时卡住按回车才动

当CMD命令提示符出现卡住现象,只需通过鼠标操作解决:点击标题栏,右键选择属性,取消勾选快速编辑模式,即可避免输入回车才能继续的问题。 原因 快速编辑模式阻塞控制台输出 解决 鼠标移动至标题栏->单击鼠标右键->属性->取消勾选快速编辑模式

别再吹牛逼说什么零延迟了,不可能的事

关于流媒体推拉流延时的几点说明。经常看到一些流媒体相关的程序,号称零延迟,不用怀疑,这肯定吹牛逼的。 搞音视频开发,有个核心的指标就是实时性,也就是延迟多少毫秒,这个问题问的也是最多的。 音视频文件几乎不存在实时性问题,只有音视频流才有实时性的指标。 延迟多久…

css的属性选择器使用

感谢 https://www.runoob.com/css/css-attribute-selectors.html 的底部评论 https://www.runoob.com/cssref/css-selectors.html 虽然一直有用到属性选择器,但是缺乏全面的了解,都是用到了就百度,看到一个大佬的总结评论,做个记录 CSS 属性选择器 ~=, |=, ^=, $=, *= 的区别 …

AdEMAMix: 一种创新的神经网络优化器

这是9月发布的一篇论文,Pagliardini等人在其论文中提出了一种新的优化算法——AdEMAMix。这种算法旨在解决当前广泛使用的Adam及其变体(如AdamW)在利用长期梯度信息方面的局限性。研究者们通过巧妙地结合两个不同衰减率的指数移动平均(EMA),设计出了这种新的优化器,以更…

Vue 基本使用

基本使用,组件使用❗必须要会! 高级特性 不常用,但可以体现你的知识深度 Vuex 和 Vue router❗重要 考察频率高面试题👇1. 指令 插值computed和watchcomputed的值没变,会缓存起来 watch 深度监听: deep: true,有子属性会遍历下去。 class和style 动态属性、驼峰写法条件…

绘制印章的开源工具DrawStampUtils使用

最近写了一个绘制印章的工具DrawStampUtils,具有比较完整的印章修改效果,定制化度较高,git地址(https://github.com/xxss0903/drawstamputils),也可以在npmjs中搜索DrawStampUtils即可// 将要绘制的canvas组件的引用传入,还有就是对应的毫米转像素的大小传入即可const sta…

从零开始学机器学习——什么是机器学习

机器学习作为人工智能的重要组成部分,通过算法自动发现数据中的模式和规律,从而使我们能够做出预测和决策。在学习过程中,我们强调了重要的关键词汇和步骤,包括训练数据集、模型、训练方法和调优过程。这个系列的文章旨在为初学者提供机器学习知识,避免使用专业术语和复杂…

Spark(八)SparkSQL概述

概述Hive是将SQL转为MapReduce SparkSQL可以理解成是将SQL解析成:“RDD+优化”再执行 SparkSQL可以简化RDD的开发,提高开发效率,且执行效率非常快 Spark SQL为了简化RDD的开发,提高开发效率,提供了2个编程抽象,DataFrame和DataSet,类似Spark Core中的RDD1. SparkSQL特点易…

Linux C++ 开发10 - 手把手教你使用valgrind性能分析工具

1. 什么是valgrind? 2. (Ubuntu)安装valgrind 3. valgrind工具的使用3.1. 命令的语法格式 3.2. 工具选项 3.3. LOG信息输出 3.4. Demo演示《Linux C++ 开发9 - 手把手教你使用gprof性能分析工具》一文中,我们讲解了gprof工具的使用方法,本文将继续讲解valgrind工具的使用方法…

js DOM学习的综合样例

js DOM学习的综合样例 本人简单学习了一点md语法,写出来的博客会更好看喵. 样例介绍 主要实现利用DOM的获取标签对象的功能和对监听功能实现三个功能:(1)开灯,关灯(2)对标签进行全选,反选(3)对文本框聚焦时字母为大写,反之为小写基本实现方法(1)开灯关灯:a.用img标签贴图关灯的…

救园最后7天:「坚持你所相信的,相信你所坚持的」

从7月15日开始的救园还剩最后7天,很有希望,也很紧张,能否救园成功,取决于最后7天有多少园友出手相救。前二十年,我们选择了「坚持我们所相信的」,相信真心为开发者服务,一定会有出路,我们坚持了下来。在第二十年遇到最大难关时,我们选择了「相信我们所坚持的」从7月15…