Go—临时对象池 sync.Pool

1. sync.Pool 是什么?

它是一个临时对象缓存,而不是一个持久的"池"。关键在于,存储在 Pool 中的对象可能会在没有任何通知的情况下被垃圾回收机制(GC)清除。因此,它不适合用来管理像数据库连接或 Socket 连接这类需要长期保持的资源。

2. sync.Pool 有什么用?

它的核心价值在于减轻垃圾回收(GC)的压力,提升性能。

对于那些需要被频繁创建和销毁的对象,使用 sync.Pool 可以将暂时不用的对象缓存起来。当下次需要时,可以直接从 Pool 中获取,避免了重新分配内存的开销,从而提高了程序的效率。

3. sync.Pool 怎么用?

使用起来非常简单,主要涉及 New、Get 和 Put 三个部分。

go 复制代码
package main

import (
    "fmt"
    "sync"
)

func main() {
    // 1. 创建一个 Pool
    p := &sync.Pool{
        // New 是一个可选的函数。当 Get() 发现池中没有可用对象时,
        // 会调用这个函数来创建一个新的对象。
        New: func() interface{} {
            fmt.Println("Creating a new object")
            return 0
        },
    }

    // 2. 从池中获取对象
    // 第一次获取,池是空的,所以会调用 New 函数
    a := p.Get().(int)
    fmt.Println("Get a:", a) // 输出 0

    // 3. 将一个对象放回池中
    p.Put(100)

    // 4. 再次获取对象
    // 这次池中有上一步 Put 的对象,所以直接获取,不会调用 New
    b := p.Get().(int)
    fmt.Println("Get b:", b) // 输出 100

    // 5. 再次获取,池又空了,会再次调用 New
    c := p.Get().(int)
    fmt.Println("Get c:", c) // 输出 0
}

关键点:

  • 线程安全:可以在多个 Goroutine 中安全地使用。
  • 大小无限制:理论上可以缓存无限多的对象,仅受限于内存。
  • 生命周期短暂 :sync.Pool 会在每次 GC 开始前,清空所有缓存的对象。所以它的缓存有效期约等于两次 GC 之间的间隔。

4. 内部工作原理与开销

为了在多 Goroutine 环境下实现高效,sync.Pool 的设计精髓在于减少锁竞争。

  • 它为每个处理器(P)都分配了一个本地的子池。
  • 每个子池包含一个私有对象 (仅当前 P 可访问,无需加锁)和一个共享列表(可被其他 P "偷取",访问时需要加锁)。

Get(获取)过程:

  1. 优先从当前 P 的私有对象获取(无锁)。
  2. 如果私有对象为空,则从当前 P 的共享列表获取(需要加锁)。
  3. 如果共享列表也为空,则尝试从其他 P 的共享列表**"偷"**一个(需要加锁)。
  4. 如果都失败了,最后才会调用 New 方法创建一个全新的对象。

Put(放回)过程:

  1. 优先尝试放到当前 P 的私有对象中(无锁)。
  2. 如果私有对象已被占用,则放入当前 P 的共享列表(需要加锁)。

总结 :sync.Pool 通过为每个 P 设置本地缓存的机制,大大减少了多核环境下的锁竞争,使得大部分 Get/Put 操作都能无锁完成。虽然它自身也有一定的开销,但相比于频繁创建对象带来的 GC 压力,对于特定场景来说,收益是非常显著的。

juejin.cn/post/684490...

相关推荐
Bazingga1 小时前
一次推理的完整旅程:ReAct推理深度解析
后端
姜鱼问生1 小时前
Nginx gzip 压缩:一个配置让页面加载快 3 倍
后端·算法·架构
颜酱1 小时前
一栋商业大厦,讲清 InnoDB 的表空间、段、区和页
后端·mysql
码事漫谈1 小时前
1956 亿行数据该怎么存:金仓时序数据库的三个实测
后端
Wx-bishekaifayuan1 小时前
springboot桂味美食分享系统40540-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
彭亚川Allen2 小时前
从零手搓 RAG 之检索全流程,给大模型接上自己的知识库
前端·后端·ai编程
IT_陈寒2 小时前
别让Java字符串拼接偷偷吃掉你的内存
前端·人工智能·后端
_Evan_Yao2 小时前
前后端联调怎么排查问题?从 Network 到后端日志,一步步定位错误
开发语言·后端·团队开发·需求分析
程序员梅雨2 小时前
ZooKeeper面经总结
java·大数据·linux·分布式·后端·zookeeper·中间件
蜗牛互联网3 小时前
Java 17 调用视觉 Responses API:JSON 约束与人工复核路由
java·人工智能·后端