golang 标准库 sync.Map 中 nil 和 expunge 区别
本文不是 sync.Map 源码详细解读,而是聚焦 entry 的不同状态,特别是 nil 状态和 expunge 状态的区分。
entry 是 sync.Map 存放值的结构体,其值有三种,分别为 value(真正的值)、nil、expunge(任意的指针,标记作用)。如果将其视为一种状态机的话,本文将其三种状态分别称之为value、nil、expunge。
简要概括:
value 状态:entry 里面存放的是真正的值。此时 entry 对应的 key,有三种情况,key 只在 read 中均存在;key 只在 dirty 中存在;在 read 和 dirty 中均存在。
nil 状态:read 中的 key 被删除的时候将其对应的 value(即 entry) p 值设置为 nil。此时 key 只存在 read 中 (ditry 为 nil);在 read 和 dirty 中均存在。
expunge 状态: 此时 key 只存在 read 中而在 dirty 中不存在。
将 sync.Map 抽象为 存、取、删除 三种操作。在这三种操作中来看 entry 状态的改变。
1、存:对于初始状态的 sync.Map, 一个新键值对 k: A v: A, 首先存放在 dirty 中,此时 entry 为 value 状态,key 只存在 dirty 中。
2、取:首先 read 中不存在,从 dirty 中取值。数次从 read 中取不中,将 dirty 提升为 read, dirty 被清空。entry 仍为 value 状态,对应的 key 存在于 read 中。
3、存:另一键值对k:B v:B,存入时,发生 read 向 dirty 拷贝,同时 read 的 amended 标记为 true。此时 key A 存在于 read 和 dirty 中,entry 为 value 状态。
4、删除:删除 key A,A 的 entry 中 p 值被设置为 nil。此时 key A 存在于 read 和 dirty 中,entry 为 nil 状态。
5、存:另一键值对k:C v:C。
6、取:多次读取 key C,触发 dirty 提升为 read,dirty 被清空。此时 key A 只存在于 read 中, entry 为 nil 状态。
7、存:另一键值对 k:D v:D, 存入时,发生 read 向 dirty 拷贝,key A 的 entry 由 nil 状态转变为 expunge 状态,key A 只存在于 read 中。
8、取:多次读取 key D,触发 dirty 提升为 read, dirty 被清空,此时 key A 被完全删除。
为什么会用 nil 和 expunge 两种状态来标记一个值的删除?
首先明确,什么时候 expunge 出现。当key A 的值在 read 中为 nil,随后由其他操作触发 read 向 dirty 复制,nil 被转变为 expunge。此时 dirty 不为空,且 key A 在 dirty 中不存在。如果对 key A 重新赋值,修改 read 后,需要同步修改 dirty ,为了保障当 dirty 提升为 read 时,包含所有的值。
再来看 nil 的清空,当 key A 的值为 nil 状态的时候,key A 存在于 read 和 dirty 中或仅存在于 read 中(dirty 为空),因为 read 和 dirty 中相同的 key 指向同一值的指针,因此在这两种情况下,对 key A 重新赋值,均无需考虑 dirty。
golang 标准库 sync.Map 中 nil 和 expunge 区别的更多相关文章
- golang 标准库间依赖的可视化展示
简介 国庆看完 << Go 语言圣经 >>,总想做点什么,来加深下印象.以可视化的方式展示 golang 标准库之间的依赖,可能是一个比较好的切入点.做之前,简单搜了下相关的内 ...
- Golang 标准库log的实现
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1406905 前 ...
- golang标准库 context的使用
本文索引 问题引入 context包简介 示例 问题引入 goroutine为我们提供了轻量级的并发实现,作为golang最大的亮点之一更是备受推崇. goroutine的简单固然有利于我们的开发,但 ...
- Go 标准库 —— sync.Mutex 互斥锁
Mutex 是一个互斥锁,可以创建为其他结构体的字段:零值为解锁状态.Mutex 类型的锁和线程无关,可以由不同的线程加锁和解锁. 方法 func (*Mutex) Lock func (m *Mut ...
- Golang 标准库提供的Log(一)
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://gotaly.blog.51cto.com/8861157/1405754 G ...
- golang标准库分析之net/rpc
net/rpc是golang提供的一个实现rpc的标准库.
- golang 标准库
前言 不做文字搬运工,多做思路整理 就是为了能速览标准库,只整理我自己看过的...... 最好能看看英文的 标准库 fmt strconv string 跳转 golang知识库总结
- STL标准库-容器-map和multimap
技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 map与multimap为关联容器,结构如下 map底层实现依然是rb_tree 他的data可以改,但是key不能改,因此ma ...
- C 标准库IO缓冲区和内核缓冲区的区别
1.C标准库的I/O缓冲区 UNIX的传统 是Everything is a file,键盘.显示器.串口.磁盘等设备在/dev 目录下都有一个特殊的设备文件与之对应,这些设备文件也 ...
随机推荐
- linux之crontab定时器
一.安装crontab yum -y install vixie-cron yum -y install crontabs 说明:vixie-cron 软件包是 cron 的主程序:crontabs ...
- Django学习系列7:使用模板解决“不测试常量”规则,使用模板重构
之前写的lists/tests.py中的单元测试,要查找特定的HTML字符串,但这不是测试HTML的高效方法. 单元测试规则之一“不测试常量”,编写断言检测HTML字符串中是否有制定的字符串序列,不是 ...
- Linux查看磁盘空间大小
1. Ubuntu 查看磁盘空间大小命令 df -h Df命令是linux系统以磁盘分区为单位查看文件系统,可以加上参数查看磁盘剩余空间信息, 命令格式: df -hl 显示格式为: 文件系统 容 ...
- web性能优化--减少DOM操作(三)
减少DOM数量 减少DOM操作 批量处理DOM操作 批量处理样式修改 尽量不要使用tabel布局 尽量不要使用css表达式 string用数组join css选择符优化 1.减少DOM数量 在HTML ...
- (转载)自然语言处理中的Attention Model:是什么及为什么
转载说明来源:http://blog.csdn.net/malefactor/article/details/50550211 author: 张俊林 原文写得非常好! 原文: 要是关注深度学习在自然 ...
- 牛客网 TaoTao要吃鸡 ( 0/1背包变形 )
题意 : 题目链接 分析 : 如果没有 BUG (即 h == 0 的时候)就是一个普通的 0 / 1 背包 需要讨论一下 h != 0 的情况 此时有就相当于有物品是有特权的 而且背包装有特权的物 ...
- UI编辑
UI编辑 基本部件介绍 (1)Layout(布局) (2)Space(空间) (3)Button (4)ItemView (5)ItemWidget Widget继承自View,即ListWidget ...
- HDU 6578 Blank
hdu题面 Time limit 1000 ms Memory limit 262144 kB OS Windows Source 2019 Multi-University Training Con ...
- 数据科学20个最好的Python库
Python 在解决数据科学任务和挑战方面继续处于领先地位.去年,我们曾发表一篇博客文章 Top 15 Python Libraries for Data Science in 2017,概述了当时业 ...
- es之批量提交操作
1:批量查询操作 1):插入测试数据 PUT /costumer/doc/1{ "name": "zhangsan", "age": 20} ...