实际使用场景
用了sync.Pool以后,能降低一部分gc,但是会增加cpu的消耗,而且会增加代码复杂度,除非特别需要的场景,不然不建议使用。
为什么 sync.Pool 不适合用于像 socket 长连接或数据库连接池?
因为,我们不能对 sync.Pool 中保存的元素做任何假设,以下事情是都可以发生的:
- Pool 池里的元素随时可能释放掉,释放策略完全由 runtime 内部管理;
- Get 获取到的元素对象可能是刚创建的,也可能是之前创建好 cache 住的。使用者无法区分;
- Pool 池里面的元素个数你无法知道;
所以,只有的你的场景满足以上的假定,才能正确的使用 Pool 。sync.Pool 本质用途是增加临时对象的重用率,减少 GC 负担。划重点:临时对象。所以说,像 socket 这种带状态的,长期有效的资源是不适合 Pool 的。
总结
-
sync.Pool 本质用途是增加临时对象的重用率,减少 GC 负担;
-
不能对 Pool.Get 出来的对象做预判,有可能是新的(新分配的),有可能是旧的(之前人用过,然后 Put 进去的);
-
不能对 Pool 池里的元素个数做假定,你不能够;
-
sync.Pool 本身的 Get, Put 调用是并发安全的,
sync.New指向的初始化函数会并发调用,里面安不安全只有自己知道; -
当用完一个从 Pool 取出的实例时候,一定要记得调用 Put,否则 Pool 无法复用这个实例,通常这个用 defer 完成;