GO的临时对象池sync.Pool
GO的临时对象池sync.Pool
文章目录
- GO的临时对象池sync.Pool
- 一、临时对象池:sync.Pool
- 1.1 临时对象的特点
- 1.2 临时对象池的用途
- 1.3 sync.Pool 的用法
- 二、临时对象池中的值会被及时清理掉
- 2.1 池清理函数
- 2.2 池汇总列表
- 2.3 临时对象池存储值所用的数据结构
- 2.4 临时对象池如何利用内部数据结构来存取值
- 2.5 池清理函数的作用机理
- 三、示例
一、临时对象池:sync.Pool
sync.Pool 类型可以被称为临时对象池,它的值可以被用来存储临时的对象。
sync.Pool 也属于结构体类型,它的值被真正使用过之后,不应该再被复制了。
1.1 临时对象的特点
-
不需要持久使用的某一类值。
这类值对程序来说可有可无,但如果有的话明显会更好。它们的创建和销毁可以再任何时候发生,并且完全不影响到程序的功能。
-
它们也是无需被区分的。
其中的任何一个值都可以替换另一个。
1.2 临时对象池的用途
临时对象池的主要用途是:当作针对某类数据的缓存来用。
1.3 sync.Pool 的用法
sync.Pool类型只有两个方法——Put和Get。
-
Put用于在当前的池中存放临时对象,它接受一个
interface{}类型的参数; -
Get用于从当前的池中获取临时对象,它返回一个
interface{}类型的参数;Get方法可能会从当前的池中删除掉任何一个值,然后把这个值作为结果返回。如果此时当前的池中没有任何值,那么这个方法就会使用当前池的New字段创建一个新值,并直接将其返回。
该函数的结果值,并不会被存入当前的临时对象池中,而是直接返回给Get方法的调用方。
sync.Pool类型的New字段代表着创建临时对象的函数。
New字段的类型是没有任何参数但有唯一结果的函数类型,即:func() interface{}。
这个函数是Get方法最后的临时对象获取手段。
sync.Pool的New字段的实际值需要在初始化临时对象池的时候给定。否则,我们调用它的Get方法的时候就有可能会得到nil。
二、临时对象池中的值会被及时清理掉
为什么说临时对象池中的值会被及时清理掉?
因为,Go语言运行时系统中的垃圾回收器,在每次执行之前,都会对已创建的临时对象池中的值进行全面的清除。
2.1 池清理函数
sync包在被初始化的时候,会向Go语言运行时系统注册一个函数,这个函数的功能就是清理所以已创建的临时对象池中的值。我们把这个函数称为池清理函数。
一旦池清理函数被注册到Go语言运行时系统,Go语言运行系统在每次执行垃圾回收之前,都会执行池清理函数。
2.2 池汇总列表
在sync包中有一个包级私有的全局变量,这个变量代表了当前程序中使用的所有临时对象池的汇总,它是元素类型为*shnc.Pool的切片。我们可以称之为池汇总列表。
通常,在一个临时对象池的Put方法和Get方法第一次被调用的时候,这个池就会添加到池汇总列表中。正因为如此,池清理函数总能访问到所有正在被真正使用的临时对象池。
2.3 临时对象池存储值所用的数据结构
在临时对象池中,有一个多层的数据结构。
正是由于它的存在,临时对象池才能够非常高校的存储大量的值。
(1)本地池列表
这个数据结构的顶层,我们称为本地池列表,确切地说,它是一个数组。这个数组的长度总是与Go语言调度器中的P的数量相同。
在Go语言调度器中,P是processor的缩写,它是一种可以承载若干个G、且能使G适时地与M进行对接,并得到真正运行的中介。
这里的G时goroutine缩写。而M是machine的缩写,machine代表系统级的线程。
正是由于P的存在,G和M才能够进行灵活、高校地配对,并实现强大的并发模型。
(2)本地池列表的长度与P的数量相同
P存在的一个重要原因是分散并发程序的执行压力,而让临时对象池中的本地池列表长度与P数量相同的主要原因也是分散压力。这里的压力是存储和性能两方面。
(3)本地池列表中的每个本地池
本地池列表中的每个本地池都包含三个字段:存储私有临时对象的字段private、代表共享临时对象列表字段shared、以及一个sync.Mutex类型的嵌入字段。
(4)本地池与G、P的关系
每个本地池都对应一个P。一个goroutine要想真正的运行,就必须先与某个P产生关联。也就是说,一个正在运行的goroutine必然会关联某个P。
在程序调用临时对象池的Put和Get方法的时候,总是依据当前的goroutine关联的那个P的ID,选取与之对应的本地池。
2.4 临时对象池如何利用内部数据结构来存取值
(1)共享临时对象列表:shared字段的可访问范围
一个本地池的shared字段原则上可以被任何goroutine中的代码访问到。不论这个goroutine关联的是哪一个P。这也是我们把它叫做共享临时对象列表的原因。
(2)private字段
一个本地池的private字段,只可能被与之对应的那个P所关联的goroutine中的代码访问到。所以可以说,它是P级私有的。
(3)Put方法
临时对象池的Put方法总会试图把新的临时对象,存储到对应的本地池的private字段中,以便获取临时对象的时候,可以快读拿到一个可用的值。只有当这个private字段已经存在某个值当时候,该方法才会访问本地池的shared字段。
临时对象池的Put方法,它一旦发现对应的本地池的private字段以存在值,就会去访问这个本地池的shared字段。由于shared字段是共享的,所以此时必须受到互斥锁的保护。这时本地池的嵌入的类型为sync.Mutex的字段就派上用场了。
(4)Get方法
相应的,临时对象池的Get方法,总会试图从对应的本地池的private字段处获取一个临时对象。只有当这个private字段的值为nil时,它才会在互斥锁的保护下访问本地池的shared字段(共享临时对象列表),把共享临时对象列表中的最有一个元素值取出并作为结果。
不过这时共享临时对象列表也可能是空的,Get方法会去访问当前的临时对象池中的所有本地池,它会去逐个搜索它们的共享临时对象列表。
这样如果仍无法获取可用的临时对象,Get方法就会使出最后的手段——调用可创建临时对象的那个函数。这个函数是由临时对象池的New字段代表,如果这个字段的值为nil,那么Get方法也只能返回nil了。
2.5 池清理函数的作用机理
池清理函数会遍历池汇总列表。对于其中的每一个临时对象池,它都会将池中所有的私有临时对象(private字段)和共享临时列表(shared字段)都置为nil,然后再把这个池中的所有本地池列表都销毁掉。
最后,池清理函数会把池汇总列表重制为空的切片。如此以来,池清理函数就把池汇总列表重置为空的切片。池中的临时对象也就被清除干净了。
三、示例
package mainimport ("bytes""fmt""io""sync"
)// bufPool 代表存放数据缓冲区的临时对象池
var bufPool sync.Pool// Buffer 代表一个简单的数据块缓冲区的接口
type Buffer interface {// Delimiter 用于获取数据块之间的定界符Delimiter() byte// write 用于写一个数据块Write(contents string) (err error)// Read 用于读一个数据块Read() (contexts string, err error)// Free 用于释放当前的缓冲区Free()
}// myBuffer 代表了数据块缓冲区的一种实现
type myBuffer struct {buf bytes.Bufferdelimiter byte
}func (b *myBuffer) Delimiter() byte {return b.delimiter
}func (b *myBuffer) Write(contexts string) (err error) {if _, err = b.buf.WriteString(contexts); err != nil {return}return b.buf.WriteByte(b.delimiter)
}func (b *myBuffer) Read() (contexts string, err error) {return b.buf.ReadString(b.delimiter)
}func (b *myBuffer) Free() {bufPool.Put(b)
}// delimiter 代表预定义的定界符
var delimiter = byte('\n')// GetBuffer 用于获取一个数据块缓冲区
func GetBuffer() Buffer {return bufPool.Get().(Buffer)
}func init() {bufPool = sync.Pool{New: func() any {return &myBuffer{delimiter: delimiter}},}
}func main() {buf := GetBuffer()defer buf.Free()// buf := &myBuffer{delimiter: delimiter}buf.Write("一个池是一个临时对象集合,这些对象能够单独的保存和释放。")buf.Write("一个池让多个goroutine同时使用也是安全的。")buf.Write("一个池在第一次被使用之后,不能被拷贝")fmt.Println("数据块在缓冲区中")for {block, err := buf.Read()if err != nil {if err == io.EOF {break}panic(fmt.Errorf("未知的错误:%s", err))}fmt.Print(block)}
}
相关文章:
GO的临时对象池sync.Pool
GO的临时对象池sync.Pool 文章目录GO的临时对象池sync.Pool一、临时对象池:sync.Pool1.1 临时对象的特点1.2 临时对象池的用途1.3 sync.Pool 的用法二、临时对象池中的值会被及时清理掉2.1 池清理函数2.2 池汇总列表2.3 临时对象池存储值所用的数据结构2.4 临时对象…...
高精度算法一
目录 1. 基础知识 2. 大整数 大整数 3. 大整数 - 大整数 1. 基础知识 利用计算机进行数值计算,有时会遇到这样的问题:有些计算要求精度高,希望计算的数的位数可达几十位甚至几百位,虽然计算机的计算精度也算较高了,…...
2023年全国最新食品安全管理员精选真题及答案1
百分百题库提供食品安全管理员考试试题、食品安全员考试预测题、食品安全管理员考试真题、食品安全员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 11.预包装食品的标签内容应使用规范的汉字,但可以同时使用&a…...
C++入门:引用
目录 一. 什么是引用 1.1 引用的概念 1.2 引用的定义 二. 引用的性质和用途 2.1 引用的三大主要性质 2.2 引用的主要应用 三. 引用的效率测试 3.1 传值调用和传引用调用的效率对比 3.2 值返回和引用返回的效率对比 四. 常引用 4.1 权限放大和权限缩小问题 4.2 跨…...
SpringSecurity的权限校验详解说明(附完整代码)
说明 SpringSecurity的权限校是基于SpringSecurity的安全认证的详解说明(附完整代码) (https://blog.csdn.net/qq_51076413/article/details/129102660)的讲解,如果不了解SpringSecurity是怎么认证,请先看下【SpringSecurity的安…...
Java-集合(5)
Map接口 JDK8 Map接口实现子类的特点 Map和Collection是并列关系,Map用于保存具有映射关系的数据:Key-ValueMap中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中Map中的key不允许重复,原因和HashSet一样Map…...
研制过程评审活动(四)设计定型阶段
1、设计定型阶段主要任务 设计定型的主要任务是对武器装备性能和使用要求进行全面考核,以确认产品是否达到《研制任务书》和《研制合同》的要求。 设计定型阶段应最终确定《产品规范》、《工艺规范》和《材料规范》的正式版本,并形成正式的全套生产图样、有关技术文件及目…...
【Linux】进程替换
文章目录进程程序替换替换原理替换函数函数返回值函数命名理解在makefile文件中一次生成两个可执行文件总结:程序替换时运行其它语言程序进程程序替换 程序要运行要先加载到内存当中 , 如何做到? 加载器加载进来,然后程序替换 为什么? ->冯诺依曼 因为CPU读取数据的时候只…...
LeetCode171-Excel表列序号(进制转换问题)
LeetCode171-Excel表列序号1、问题描述2、解题思路:进制转换3、代码实现1、问题描述 给你一个字符串columnTitle,表示Excel表格中得列名称。返回该列名称对应得列序号。 例如: A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 …...
React SSR
ReactDOMServer 参考链接:https://zh-hans.reactjs.org/docs/react-dom-server.html ReactDOMServer 对象允许你将组件渲染成静态标记。通常,它被使用在 Node 服务端上 // ES modules import * as ReactDOMServer from react-dom/server; // CommonJS v…...
如何系统地优化页面性能
页面优化,其实就是要让页面更快地显示和响应。由于一个页面在它不同的阶段,所侧重的关注点是不一样的,所以如果要讨论页面优化,就要分析一个页面生存周期的不同阶段。 通常一个页面有三个阶段:加载阶段、交互阶段和关…...
Vulnhub 渗透练习(八)—— THE ETHER: EVILSCIENCE
环境搭建 环境下载 靶机和攻击机网络适配都选 NAT 即可。 信息收集 主机扫描 两个端口,22 和 80,且 apache httpd 2.4.0~2.4.29 存在换行解析漏洞。 Apache HTTPD是一款HTTP服务器,它可以通过mod_php来运行PHP网页。其2.4.0~2.4.29版本中…...
华为OD机试题 - 水仙花数 2(JavaScript)| 代码+思路+重要知识点
最近更新的博客 华为OD机试题 - 字符串加密(JavaScript) 华为OD机试题 - 字母消消乐(JavaScript) 华为OD机试题 - 字母计数(JavaScript) 华为OD机试题 - 整数分解(JavaScript) 华为OD机试题 - 单词反转(JavaScript) 使用说明 参加华为od机试,一定要注意不要完全背…...
字符设备驱动基础(二)
目录 一、五种IO模型------读写外设数据的方式 二、阻塞与非阻塞 三、多路复用 3.1 应用层:三套接口select、poll、epoll 3.2 驱动层:实现poll函数 四、信号驱动 4.1 应用层:信号注册fcntl 4.2 驱动层:实现fasync函数 一、…...
看见统计——第三章 概率分布
看见统计——第三章 概率分布 参考 https://github.com/seeingtheory/Seeing-Theory中心极限定理 概率分布描述了随机变量取值的规律。 随机变量Random Variables 🔥 定义:将样本空间中的结果映射到实数的函数 XXX 称为随机变量(random variable)&a…...
【基于众包标注的语文教材句子难易度评估研究 论文精读】
基于众包标注的语文教材句子难易度评估研究 论文精读信息摘 要0 引言1 相关研究2 众包标注方法3 语料库构建3.1 数据收集3.1 基于五点量表的专家标注3.3 基于成对比较的众包标注4 特征及模型4.1 特征抽取4.2 模型与实验设计4.2.1 任务一:单句绝对难度评估4.2.2 任务二:句对相对…...
实例五:MATLAB APP design-APP登录界面的设计
一、APP 界面设计展示 注:在账号和密码提示框输入相应的账号和密码后,点击登录按钮,即可跳转到程序中设计的工作界面。 二、APP设计界面运行结果展示...
作用域和闭包:
1、LHS和RHS查询编译一段代码,需要js引擎和编译器(js引擎负责整个程序运行时所需的各种资源的调度,编译器只是js引擎的一部分,负责将JavaScript源码编译成机器能识别的机器指令,然后交给引擎运行)编译的过程…...
Vue常见面试题?
1、说说你对SPA单页面的理解,它的优缺点是什么? SPA(single-page application)仅在Web页面初始化时加载相应的HTML、JavaScript和CSS。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机…...
前端借助Canvas实现压缩图片两种方法
一、具体代码 1、利用canvas压缩图片方法一 // 第一种压缩图片方法(图片base64,图片类型,压缩比例,回调函数)// 图片类型是指 image/png、image/jpeg、image/webp(仅Chrome支持)// 该方法对以上三种图片类型都适用 压缩结果的图片base64与原类型相同// …...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
