1.基本概念
正如sycn.Pool的名字所示,这是go中实现的一个对象池,为什么要有这个池呢?首先go是自带垃圾回收机制(也就是通常所说的gc)。gc会带来运行时的开销,对于高频的内存申请与释放,如果将不用的对象存放在一个池子中,用的时候从池子中取出一个对象,用完了再还回去,这样就能减轻gc的压力。
对于池这个概念,之前可能听说过连接池。能否用sync.Pool实现一个连接池呢?答案是不能的。因为对于sync.Pool而言,我们无法保证每次放回去再取出来的对象是与之前一致的,对象的内存存在着呗销毁的可能。因此,这个sync.Pool的存在仅仅是为了减缓gc的压力而生的。
2.特点
- sync.Pool是一个存储临时对象的对象池
- 任何存储在sync.Pool中的变量随时都有可能被销毁,并且销毁的同时没有任何通知
- pool中的对象数量是不可控的
- 当pool中只有一个对象时,这块内存有可能被回收
- sync.Pool是协程安全的
3.基本用法
import (
"fmt"
"sync"
)
func main() {
p := &sync.Pool{
New: func() interface{} {
return "test"
},
}
s := p.Get().(string)
fmt.Println(s)
p.Put(s)
}
定义sync.Pool的时候只需要设置一个New成员,它是一个函数,类型为func() interface{},当池子中没有空闲的对象时就会调用New函数生成一个。由于pool中对象的数量不可控,因此并没有传递任何与对象数量有关的参数。
然后,调用调用Get函数就可以取出一个对象,调用Put函数就可以将对象归还到池子中。
4.相关的数据结构
type Pool struct {
noCopy noCopy //不允许复制
local unsafe.Pointer // 指向一个poolLocal类型的变量
localSize uintptr // size of the local array
victim unsafe.Pointer // local from previous cycle
victimSize uintptr // size of victims array
New func() interface{}
}
type poolLocal struct {
poolLocalInternal
// Prevents false sharing on widespread platforms with
// 128 mod (cache line size) = 0 .
pad [128 - unsafe.Sizeof(poolLocalInternal{})%128]byte
}
// Local per-P Pool appendix.
type poolLocalInternal struct {
private interface{} // Can be used only by the respective P.
shared poolChain // Local P can pushHead/popHead; any P can popTail.
}