Go 是一种有自动垃圾回收机制的编程语言,采用三色并发标记算法标记对象并回收。和其他没有自动垃圾回收机制的编程语言不同,使用 Go 语言创建对象时,我们没有回收/释放的心理负担,想创建对象就创建,想用对象就用。
但是,如果想使用 Go 语言开发一个高性能的应用程序,就必须考虑垃圾回收给性能带来的影响,毕竟 Go 的自动垃圾回收机制有一个STW(stop-the-world,程序暂停)的时间,而且在堆上大量地创建对象,也会影响垃圾回收标记的时间。所以,我们在做性能优化时,通常会采用对象池的方式,把不用的对象回收起来,避免被垃圾回收,这样使用时就不必在堆上重新创建对象了。
不仅如此,像数据库连接、TCP 的长连接等,这些连接的创建也是一个非常耗时的操作。如果每次使用时都创建一个新的连接,则很可能整个业务的很多时间都花在了创建连接上。所以,如果能把这些连接保存下来,避免每次使用时都重新创建,则不仅可以大大减少业务的耗时,还能提高应用程序的整体性能。
这种模式被称为对象池设计模式(object pool pattern) 。一个对象池包含一组已经初始化过且可以重复使用的对象,池的用户可以从池子中获得对象,对其进行操作处理,并在不需要的时候归还给池子,而非直接销毁它。
若初始化对象的代价很高,且经常需要实例化对象,但实例化的对象数量较少,那么使用对象池可以显著提升性能。从池子中获得对象的时间是可预测的且时间花费较少,而新建一个实例所需的时间是不确定的,可能时间花费较多。
Go标准库中提供了一个通用的 Pool 数据结构,也就是 sync.Pool,我们使用它可以创建池化的对象。
1. sync.Pool 的使用方法
首先,我们来介绍 Go 标准库中提供的 sync.Pool 数据类型。
sync.Pool 数据类型用来保存一组可独立访问的 “临时” 对象。请注意这里加引号的 “临时” 两个字,它说明了 sync.Pool 这个数据类型的特点--其池化的对象会在未来某个时候被毫无征兆地移除。而且,如果没有别的对象引用这个要被移除的对象,该对象就会被垃圾回收。
因为 Pool 可以有效地减少对新对象的申请,从而提高程序性能,所以 Go 内部库中也用到了 sync.Pool。比如 fmt 包,它会使用一个动态大小的 buffer 池做输出缓存,当大量的 goroutine 并发输出的时候,就会创建比较多的 buffer ,并且在不需要的时候被回收。
有两个知识点需要记住:
- sync.Pool 本身就是线程安全的,多个 goroutine 可以并发地调用它的方法存取对象。
- sync.Pool 不可在使用之后再复制使用。
这个数据类型提供了三个对外的方法:New、Get 和 Put。
1. New:创建对象
这里的 New 不是创建 Pool 类型的对象的方法,而是 Pool 对象创建其池化对象的方法。因为只有定义了创建池化对象的方法,它才能在需要的时候创建对像。
Pool struct 包含一个 New 字段,这个字段的类型是函数 func() interface{ }。当调用 Pool 的 Get 方法从池中获取对象时,如果没有更多空闲的对象可用&#x
标签:语言,对象,创建,sync,回收,Go,Pool From: https://blog.csdn.net/canglonghacker/article/details/140764172