更多干货,关注公众号:奇伢云存储
文章目录
Go 并发相关库
sync
里面有一个有趣的 package
Pool
,
sync.Pool
是个有趣的库,用很少的代码实现了很巧的功能。
第一眼看到 Pool
这个名字,就让人想到池子,元素池化是常用的性能优化的手段(性能优化的几把斧头:并发,预处理,缓存)。比如,创建一个 100 个元素的池,然后就可以在池子里面直接获取到元素,免去了申请和初始化的流程,大大提高了性能。释放元素也是直接丢回池子而免去了真正释放元素带来的开销。
但是再仔细一看 sync.Pool
的实现,发现比我预期的还更有趣。sync.Pool
除了最常见的池化提升性能的思路,最重要的是减少 GC 。常用于一些对象实例创建昂贵的场景。注意,Pool 是 Goroutine 并发安全的。
使用姿势
初始化 Pool 实例 New
第一个步骤就是创建一个 Pool 实例,关键一点是配置 New 方法,声明 Pool 元素创建的方法。
bufferpool := &sync.Pool {
New: func() interface {
} {
println("Create new instance")
return struct{
}{
}
}
}
申请对象 Get
buffer := bufferPool.Get()
Get
方法会返回 Pool 已经存在的对象,如果没有,那么就走慢路径,也就是调用初始化的时候定义的 New 方法(也就是最开始定义的初始化行为)来初始化一个对象。
释放对象 Put
bufferPool.Put(buffer)
使用对象之后,调用 Put 方法声明把对象放回池子。注意了,这个调用之后仅仅是把这个对象放回池子,池子里面的对象啥时候真正释放外界是不清楚的,是不受外部控制的。
你看,Pool 的用户使用界面就这三个接口,非常简单,而且是通用型的 Pool 池模式,针对所有的对象类型都可以用。
思考
为什么用 Pool,而不是在运行的时候直接实例化对象呢?
本质原因:Go 的内存释放是由 runtime 来自动处理的,有 GC 过程。
举个栗子:
package main
<