当前位置:首页 > 文章列表 > Golang > Go教程 > Sync.Map读写原理全解析

Sync.Map读写原理全解析

2026-05-09 11:28:56 0浏览 收藏
sync.Map 并非万能的并发安全映射,其精巧的 read/dirty 双层结构与原子操作仅在“读多写少、键生命周期长、极少遍历”的特定场景下才能发挥优势:read 依赖 atomic.Pointer 实现真正无锁读取,dirty 则通过 misses 计数器动态升级以平衡新鲜度与拷贝开销;Store 优先无锁更新,失败后才加锁处理,Delete 仅为逻辑标记,真实清理延迟至 dirty 提升时完成——但一旦写入频繁、删除密集或需定期 Range,它反而比普通 sync.RWMutex + map 更慢、更耗内存,用错场景得不偿失。

Go 语言中 sync.Map 的 read 与 dirty 机制详解

sync.Map 不是通用并发 map,它的 read/dirty 分离只在“读多写少”且键生命周期长的场景下才真正高效;用错场景反而比加锁的 map 更慢、更占内存。

read 为什么能无锁读?靠的是 atomic.Pointer + readOnly 结构体

read 字段不是普通 map,而是一个 atomic.Pointer,指向一个 readOnly 结构体。这个结构体里包含两个东西:m(底层是 map[interface{}]*entry)和 amended(布尔值)。atomic.Pointer 保证了对整个 readOnly 的替换是原子的,所以读操作只需一次原子加载,拿到指针后直接查 m,全程不碰锁。

但要注意:entry.punsafe.Pointer,读取时需用 atomic.LoadPointer 判断状态——nil 表示已删,expunged 表示该 entry 已从 dirty 中物理移除,只有其他有效指针才代表可用值。

dirty 什么时候被提升为 read?由 misses 计数器触发

每次 Loadread.m 中没找到、转去查 dirty 时,misses 就加 1。当 misses >= len(dirty),就触发提升:把整个 dirty 赋给新的 readOnly.m,清空 dirty,重置 misses 为 0,并将 read.amended 设为 false

这个阈值设计很关键:

  • 太小 → 频繁提升,拷贝开销大,dirty 刚写几条就升,失去写缓冲意义
  • 太大 → read 长期 stale,大量读被迫进锁查 dirty,并发读性能崩塌
  • Go 当前实现就是用 len(dirty) 作阈值,不暴露可调接口,你没法改

Store 操作为什么有时无锁、有时要锁?取决于 entry 是否存在且未被 expunged

Store 第一步永远是查 read.m

  • 如果 key 存在且 entry.p != expunged → 直接 atomic.StorePointer 更新值,无锁完成
  • 如果 key 不存在,或 entry.p == expunged → 必须加 mu 锁,进入 dirty 分支处理

加锁后还要双检 read(防止别的 goroutine 刚升完级),再决定是往 dirty 插新 entry,还是把 expunged 条目复活。这个“先试无锁、失败再锁”的路径,正是它读多时快的核心。

Delete 是假删除,真清理要等 dirty 提升

Delete 永远只动 read.m 里的 entry.p,把它设成 nil(标记逻辑删除),不会碰 dirty。只有当该 key 同时存在于 dirty 中时,才会在加锁后从 dirty 中真正删掉。

但更常见的情况是:key 只在 read 里,Delete 后它就一直挂着 nil,直到某次 dirty 提升为新 read 时,这些 nil entry 才被彻底过滤掉。这意味着:

  • 内存不会立刻释放,可能累积 stale 条目
  • Range 遍历时会跳过 nilexpunged,但遍历本身会强制触发一次提升,代价不小
  • 别指望 Delete 后立即减小内存占用

真正容易被忽略的是:sync.Map 的“高性能”完全绑定在 key 稳定、写入频次低、且几乎不遍历的前提下。一旦开始高频写、反复删、或者定期 Range,它的优势就迅速瓦解,甚至不如自己包一层 sync.RWMutex + map

终于介绍完啦!小伙伴们,这篇关于《Sync.Map读写原理全解析》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布Golang相关知识,快来关注吧!

PyPI包嵌入JSON读取技巧解析PyPI包嵌入JSON读取技巧解析
上一篇
PyPI包嵌入JSON读取技巧解析
Go mod tidy清理未使用包方法详解
下一篇
Go mod tidy清理未使用包方法详解
查看更多
最新文章
资料下载
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ChatExcel酷表:告别Excel难题,北大团队AI助手助您轻松处理数据
    ChatExcel酷表
    ChatExcel酷表是由北京大学团队打造的Excel聊天机器人,用自然语言操控表格,简化数据处理,告别繁琐操作,提升工作效率!适用于学生、上班族及政府人员。
    4486次使用
  • Any绘本:开源免费AI绘本创作工具深度解析
    Any绘本
    探索Any绘本(anypicturebook.com/zh),一款开源免费的AI绘本创作工具,基于Google Gemini与Flux AI模型,让您轻松创作个性化绘本。适用于家庭、教育、创作等多种场景,零门槛,高自由度,技术透明,本地可控。
    4827次使用
  • 可赞AI:AI驱动办公可视化智能工具,一键高效生成文档图表脑图
    可赞AI
    可赞AI,AI驱动的办公可视化智能工具,助您轻松实现文本与可视化元素高效转化。无论是智能文档生成、多格式文本解析,还是一键生成专业图表、脑图、知识卡片,可赞AI都能让信息处理更清晰高效。覆盖数据汇报、会议纪要、内容营销等全场景,大幅提升办公效率,降低专业门槛,是您提升工作效率的得力助手。
    4713次使用
  • 星月写作:AI网文创作神器,助力爆款小说速成
    星月写作
    星月写作是国内首款聚焦中文网络小说创作的AI辅助工具,解决网文作者从构思到变现的全流程痛点。AI扫榜、专属模板、全链路适配,助力新人快速上手,资深作者效率倍增。
    6527次使用
  • MagicLight.ai:叙事驱动AI动画视频创作平台 | 高效生成专业级故事动画
    MagicLight
    MagicLight.ai是全球首款叙事驱动型AI动画视频创作平台,专注于解决从故事想法到完整动画的全流程痛点。它通过自研AI模型,保障角色、风格、场景高度一致性,让零动画经验者也能高效产出专业级叙事内容。广泛适用于独立创作者、动画工作室、教育机构及企业营销,助您轻松实现创意落地与商业化。
    5080次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码