首页 > 编程笔记 > Go语言笔记 阅读:3

Golang sync.pool的用法(附带实例)

Go 语言本身提供了垃圾回收功能,所以通常我们都会随意地创建对象,对象使用完之后也不需要做任何处理,反正垃圾回收功能会帮助我们回收掉这些不用的对象。

但是,如果程序需要频繁地创建大量对象呢?而且这些对象的生命周期都比较短。频繁地创建对象意味着需要频繁地申请内存,生命周期都比较短意味着需要不停地回收大量内存,程序的性能必然会受到影响。

一方面需要频繁地创建大量对象,另一方面这些对象的生命周期都比较短,那能不能复用这些对象呢?也就是说,使用完对象之后,能不能临时地将对象缓存起来,创建对象的时候再从缓存中获取?这样一方面可以降低垃圾回收的成本,另一方面创建对象的性能也有所提升,一举两得。

Go 语言提供了并发对象池 sync.Pool,从对象池获取对象时,如果有空闲对象,直接返回,否则新创建一个对象返回;当然,使用完对象之后需要将对象放回对象池。

对象池的使用方式参考下面的代码:
package main
import (
    "fmt"
    "math/rand"
    "sync"
)

func main() {
    // 匿名函数,用于创建对象
    f := func() interface{} {
        fmt.Println("init new object")
        return rand.Intn(1000)
    }
    // 初始化对象池
    pool := sync.Pool{
        New: f,
    }
    c := pool.Get()    // 首次获取对象,新创建
    fmt.Println(c)
    pool.Put(c)      // 将对象放回对象池

    c1 := pool.Get() // 第二次获取对象,复用
    fmt.Println(c1)
    c2 := pool.Get() // 对象池没有空闲对象,新创建
    fmt.Println(c2)
}
在上面的代码中:
执行上面的程序后,输出结果如下所示:

init new object
81
81
init new object
887

参考上面的输出结果:
当然,对象池不仅仅能存储普通的结构体对象,还可以用来存储连接、协程等复杂对象,以此实现连接复用和协程复用。

相关文章