Pool池对象-sync.Pool

本文介绍了Go语言中的sync.Pool对象池,用于优化性能和减少内存开销。sync.Pool提供New、Get和Put方法,允许并发存取对象,但对象可能在无预警的情况下被回收。文章提醒注意不要池化长连接,如TCP或数据库连接,并提供了连接池和工作池的实现示例。同时,讨论了使用sync.Pool时的内存管理和并发控制问题。
摘要由CSDN通过智能技术生成

对于一些对象,为了优化性能,节省每次使用都创建新对象所带来的内存开销,可以使用池化技术,预先创建好一些对象放入池中,使用时从池中获取,使用完再放回池中。这样就减少了对象创建所带来的开销。

在go中,原生的池化数据结构为sync.Pool, 有三个方法:

  • New字段为一个方法,定义为func() interface{}, 在新建Pool时,定义好New字段,以供后续从池中获取对象时,如果当前池中无对象,则使用此方法来新建对象。
  • Get()方法:从池中获取对象
  • Put(x interface{})方法:将对象放入池中

使用样例:

	conPool := sync.Pool{
		New: func() interface{} { return &Con{age: 20} },
	}

	con := conPool.Get().(*Con)
	fmt.Printf("con.age: %v\n", con.Age())
	
	conPool.Put(con)

sync.Pool用于保存一组可独立访问的临时对象,注意加粗的临时,说明它池化的对象在未来某个时候会被
毫无征兆的移除掉。

go中sync.Pool的特点:

  • 池中对象数量没有最少最多限制,只要存和取,都可以成功
  • 池中的对象会被随机回收,当程序GC时,可能会回收池中对象
  • 存和取可以并发使用,本身就是线程安全的
  • 池中的对象是bytes.Buffer时,如果buffer的cap随着每次使用而变化,尽管每次使用完后buffer.Reset()清空了长度,但底层的cap仍然很大,会造成内存泄露

使用sync.Pool的注意点:

  • 因为池化对象可能会被垃圾回收,因此对于tcp链接、数据库链接等一下长连接是不合适的
  • 如果要限制池中对象的最多最少限制,需要自己在这基础上做修改
  • 如果池中对象有bytes.Buffer类型, 每次放回池之前对cap做判断,如果太大就不再放回池中,避免内存泄露

连接池

Pool 的另一个很常用的一个场景就是保持 TCP 的连接。
(事实上,很少用sync.Pool去池化连接对象,因为sync.Pool会无通知的将某个连接回收,因此
会其他方法来池化对象)

  • 标准库中的 http client 池
    http.Client 实现连接池的代码是在 Transport 类型中,它使用 idleConn 保存持久化的可重用的长连接:
  • fatih/pool的tcp连接池
    它的 Pool 是通过 Channel 实现的,空闲的连接放入到 Channel 中,这也是 Channel 的一个应用场景:
  • 数据库连接池
    通过 MaxOpenConns 和 MaxIdleConns 控制最大的连接数和最大的 idle 的连接数。
  • Memcached Client 连接池
    gomemcache是他使用 Go 开发的 Memchaced 的客户端,其中也用了连接池的方式池化 Memcached 的连接

Worker Pool

当使用并发任务时,我们常常建立一个任务池,控制并发时最少最多的goroutine数量。

总结

Pool是一个通用的概念,当程序中有很多需要重复创建的对象,可以创建池类对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值