关于golang sync.Pool
golang 官方为了解决对象重用问题提供了临时对象池:https://golang.org/src/sync/pool.go
对象池,是指提供了对象复用功能。临时是指对象池的没有引用的对象在每两分钟一次的GC中会被全部清理掉。有点坳口,下面我们来看一段代码。
package main
import (
"log"
"runtime"
"sync"
)
func main() {
p := &sync.Pool{
New: func() interface{} {
return 0
},
}
a := p.Get().(int)
p.Put(1)
b := p.Get().(int)
log.Println(a, b)
p.Put(3)
p.Put(4)
p.Put(5)
log.Println(p.Get()) //返回 3 4 5中的任意一个。
//主动调用GC pool中对象会被清理掉
runtime.GC()
p.Put(2)
c := p.Get().(int)
log.Println(c)
}
总结下这个临时对象池的特点:
- 池不可以指定大小,大小只受制于GC临界值;
- 对象的最大缓存周期是GC 周期,当GC 调用时 没有被引用的对象都会被清理掉;
- Get方法返回时是返回池中任意一个对象,没有顺序;如果池中没有对象,那么调用New方法新生成一个;如果没有指定New方法,那么返回nil;
这个pool是官方为了解决对象复用提供的方案,当然在goroutine不多的情况下使用chan 来缓存对象也可以,当goroutine多了以后,那么对chan的竞争会影响整体性能。
这么好的东西是不是可以用来实现连接池减少短连接开销呢? 答案是不能。通过上面的总结也可以看出,临时对象池的对象适合于状态无关的对象,而长连接要判断连接状态。那么哪些场景适合使用这个pool呢?