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 目录下都有一个特殊的设备文件与之对应,这些设备文件也 ...
随机推荐
- JDK12的安装搭建
JDK12的安装搭建 一.JDK下载 1.JDK官网下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk12-down ...
- C#文件路径操作总结
一.获取当前文件的路径 1. System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName 获取模块的完整路径,包括 ...
- C# WinFrom自适应
1.在窗体的Project中建一个自适应的类. 2.类的代码如下 public class AutoSizeForm { //(1).声明结构,只记录窗体和其控件的初始位置和大小. public st ...
- VMware主机使用无线上网
VMware主机使用无线上网,默认的NAT连接在ubuntu下上不了网,需要把网络适配器改成桥接模式.
- 牛客OI周赛13-提高组 比赛总结
比赛情况 1h才写出T1 100pts + T2 50pts(都是简单dp可还行).然后就去颓废了.颓废完来康康T3的暴力,wow,T3咋这么难呢!?期望概率好像不太会了,退了吧qwq. 所以最后 1 ...
- set uniion()
union()方法返回两个集合的并集,包含所有集合的元素,重复元素只会出现一次. 语法: set.union(set1,set2) 参数: set1必填参数,合并的目标集合 set2选填参数,其他要合 ...
- UVA-10480-Sabotage(最大流最小割,打印路径)
链接: https://vjudge.net/problem/UVA-10480 题意: The regime of a small but wealthy dictatorship has been ...
- 第二章 psql客户端工具
第二章 psql客户端工具 pgAdmin是一款功能丰富.开源免费的PostgreSQL图形化工具.psql是PostgreSQL自带的命令行工具,功能全面,是PostgreSQL数据库工程师必须熟练 ...
- 【NOIP2016提高A组集训第14场11.12】随机游走
题目 YJC最近在学习图的有关知识.今天,他遇到了这么一个概念:随机游走.随机游走指每次从相邻的点中随机选一个走过去,重复这样的过程若干次.YJC很聪明,他很快就学会了怎么跑随机游走.为了检验自己是不 ...
- 第九周作业—N42-虚怀若谷
一.编写脚本,接收二个位置参数,magedu和/www,判断系统是否有magedu,如果没有则自动创建magedu用户,并自动设置家目录为/www [root@centos7 data]# cat u ...