首页 > 其他分享 >go数据类型-sync.map

go数据类型-sync.map

时间:2023-11-29 16:35:16浏览次数:50  
标签:map amended read 数据类型 misses dirty key go

定义

在runtime的sync.map包中有定义:

type Map struct {
	mu Mutex // 锁
	read atomic.Pointer[readOnly] //包含了readOnly类型的一个struct,下方把 Pointer 也贴了
	dirty map[any]*entry	 // 一个map 存储数据
	misses int          // 错过、没有命中
}

// readOnly is an immutable struct stored atomically in the Map.read field.
type readOnly struct {
	m       map[any]*entry // 一个map,这个map是 read持有的
	amended bool // true if the dirty map contains some key not in m.
    // 追加,这里已经注释了 当dirty 的map中的key 不在 m的map中(就是 read的)就显示为 true
}

// go 的泛型
type Pointer[T any] struct {
	_ [0]*T
	_ noCopy
	v unsafe.Pointer
}

整体的结构就如上图。

sync.map中有两个map 都是通过指针的形式 ,指向同一份value,但是key两个map都有各自存储。

分析原理

看究竟是如何解决map并发的问题的。

正常读写

正常读写走 m,就是read那个通过泛型结构体指向的那个 map,通过m这个map进行查找后,读取或者更改。

这个时候 misses = 0 ,amended=false

追加

如何写一个key,发现m中没有,那么需要去dirty中追加。

开始追加前,需要对dirty进行上锁,写完解锁

如图现在追加了一个 d,这个时候 m中没有这个d的信息。

这个时候 misses = 0 ,amended=true 这个时候有了 dirty的key 不在m中了。

追加后读写

这时候就会出现 找d时候,发现m中没有并 amended=true ,就会去 dirty中找,而且每找一次,都会给 misses 加1

这个时候 misses = 1 ,amended=true 

dirty 提升

misses 等于 len(dirty) 就会触发dirty提升,替代m。

当再次出现追加的情况,重塑 dirty

这时候把  misses = 0 ,amended=false 复原

删除

删除比较麻烦,分为正常删除,和在上面的各种状态下进行删除。

正常删除

只需要把pointer置为nil就好,value因为没有对象指向它,在垃圾回收时候,会被标记为白色,被清理。

追加后删除

正常也是置为nil

删除后,提升

提升之后,如果重建 dirty,就不会重建这个d

这里d标记为 expunge 是为了告诉下方,
这个key已经被删除了,不用同步了,如果出现删除d的请求,不需要和下方dirty同步了。
而且当再对D进行追加时候,这时候 m中有d,但是,应该要放到dirty中去完成。

总结:

1. map 在扩容时会有并发问题

2.sync.Map 使用了两个map,分离了扩容问题

3.不会引发扩容的操作(查、改)使用read map

4.可能引发扩容的操作(新增)使用 dirty map

5.不是采用读写分离的办法

标签:map,amended,read,数据类型,misses,dirty,key,go
From: https://www.cnblogs.com/studyios/p/17864986.html

相关文章

  • go开发之基于个微机器人的二次开发
    请求URL:http://域名地址/sendText请求方式:POST请求头Headers:Content-Type:application/jsonAuthorization:login接口返回参数:参数名必选类型说明wId是string登录实例标识wcId是string接收方群idcontent是string文本内容消息(@的微信昵称需要自己拼接)at是string艾特的微信id(多个以逗号......
  • [Mac软件]Goldie App v2.2 Mac黄金比例设计工具
    Goldie应用程序是在Mac上测量和可视化黄金比例的最佳方式。从比率的任何一点进行计算,在该行的各个主题之间切换,并自定义您如何使用Goldie。这个紧凑的工具将帮助您轻松创建完美平衡的设计。灵活的尺子Goldie应用程序在您的屏幕上显示一把尺子,这简化了与黄金比例的和解。适应背景颜......
  • golang-切片
    引子因为数组的长度是固定的并且数组的长度属于类型的的一部分,所以数组有很多的局限性,例如:funcarraySum(x[3]int)int{sum:=0for_,v:=rangex{sum=sum+v}returnsum}这个求和函数稚嫩接收长度为[3]int的数组元素,其他的都不支持......
  • MongoDB的安装使用与监控
    MongoDB的安装使用与监控下载https://www.mongodb.com/try/download/community我这边习惯于下载Windows的MSI进行安装Linux喜欢下载tgz包.这样便于迁移与快速部署.安装解压缩然后将bin目录下的文件复制到/usr/bin目录下添加用户useraddmonogdb添加文件mkdir-p/......
  • kali nmap 扫描密码
    【20171115中】nmap使用脚本爆破telnet密码  今天老黑走出了低谷,设置了惩罚机制后效率提升了很多,现在写一个使用nmap检测目标主机漏洞和利用漏洞的文章,话不多说,直接开始!0x01:环境介绍主机A:系统-kali2017,IP- 192.168.1.104主机B:系统-win7x64,IP- 192.168.......
  • 基本数据类型-C语言-2023/11/29
    ......
  • 2023-11-29:用go语言,给你一个字符串 s ,请你去除字符串中重复的字母,使得每个字母只出现
    2023-11-29:用go语言,给你一个字符串s,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小。要求不能打乱其他字符的相对位置)。输入:s="cbacdcbc"。输出:"acdb"。来自左程云。答案2023-11-29:所有的代码用灵捷3.5编写,感觉有点抽风了,生成的代码需要修改......
  • 使用Golang构建高性能网络爬虫
    前段时间和以前公司的老同事聚会,喝酒中无意聊到目前他们公司在做的一个爬虫项目,因为效率低下,整个人每天忙的不可开交。借着这次聚会,正好询问我一些解决方案。于是,我给了他们我的一些思路。所谓的高性能网络爬虫就是一种能够快速、高效地从互联网上抓取大量网页数据的程序。网络爬虫......
  • Golang Gin 获取Restful参数、URL查询参数,Form 表单参数,JSON格式参数
    前言http请求中,可以通过URL查询参数提交数据到服务器,可以通过post的json方式,还有一直方式就是Form表单。Form表单相比URL查询参数,用户体验好,可以承载更多的数据,尤其是文件上传时,特别方便。这里推荐飞雪无情的博客;写了一些列的gin的使用教程,很时候新手学习如果想对gin有一个完整......
  • 亚马逊云科技基于 Polygon 推出首款 Amazon Managed Blockchain Access,助 Web3 开发人
     2023年11月26日,亚马逊(Amazon)旗下AmazonWebServices(Amazon)在其官方博客上宣布,AmazonManagedBlockchain(AMB)Access已支持PolygonProof-of-Stake(POS)网络,并将满足各种场景的需求,包括需要以高可用方式频繁访问PolygonJSON-RPCAPI的场景以及需要间歇性、不......