DefaultObjectPool<T> 必须传非 null 策略,否则 Get() 返回 default(T)(如 null);Return() 未执行或异常导致复用失败;高并发瓶颈常在 Create() 耗时或竞争,应分池;StringBuilderPool 不解决状态污染,且 new StringBuilder() 在多数场景更轻量。

直接用 DefaultObjectPoolProvider 创建池但不配策略,Get() 会返回 null 或抛 NullReferenceException —— 因为默认构造不带策略,内部只返回 default(T)。
为什么 new DefaultObjectPool 容易崩
手动 new DefaultObjectPool<StringBuilder> 时,若传入的 IPooledObjectPolicy<T> 是 null,或用了无参构造函数,内部不会创建实例,Get() 直接返回 default(StringBuilder)(即 null)。这不是 bug,是设计使然:它强制你显式声明“怎么造、怎么清”。
- 必须传非
null策略,哪怕只是new DefaultPooledObjectPolicy<StringBuilder>() -
DefaultPooledObjectPolicy<T>对StringBuilder有效(自动调Clear()),但对自定义类完全无效 —— 它只对实现了IResettable或有Clear()方法的类型做反射调用 - 不要依赖“默认就清空”,检查源码可知:它只对
StringBuilder、MemoryStream等少数 BCL 类型硬编码了清理逻辑
Return() 被跳过才是复用失败的真凶
现象是“每次 Get() 都拿到新对象”,不是池坏了,而是 Return() 根本没执行。常见断点:
- 在
async void方法里调Return(),方法提前退出,归还被丢弃 -
try块里出异常,finally没包住Return(),对象永久泄漏 -
Return()前字段已被设为null,导致策略的Return(T obj)方法内判空失败并抛异常 —— 池捕获后直接丢弃该实例,不进栈 - 池设置了
MaximumRetained = 50(DefaultObjectPoolProvider默认值),第 51 个空闲对象会被 GC,不会缓存
高并发下 Get() 变慢?别只盯着池本身
DefaultObjectPool<T> 内部用 ConcurrentStack<T>,理论无锁,但真实瓶颈常在别处:
- 对象
Create()方法里有 IO、锁、或耗时初始化(比如AutoMan()里Thread.Sleep(5000))—— 这会卡住整个线程的Get() - 多个线程争抢同一个池,
ConcurrentStack.Push()/Pop()在极端高 QPS 下仍可能因 CPU cache line bouncing 抖动 - 解决方案不是换池,而是分池:
AsyncLocal<ObjectPool<T>>每线程一个池,或按租户 ID 哈希分桶,避免竞争 -
Return()方法里禁止任何阻塞操作 —— 即使是Monitor.Enter或简单日志写入,都会拖慢所有归还路径
StringBuilderPool 有捷径,但别迷信“开箱即用”
DefaultObjectPoolProvider.CreateStringBuilderPool() 是唯一官方预置快捷方式,它等价于:
new DefaultObjectPoolProvider().Create(new DefaultPooledObjectPolicy<StringBuilder>())
但它只解决“造和清”,不解决“状态污染”:
- 如果你在
Get()后调sb.ToString()再Append(),没问题;但若中间调了sb.Length = 0或sb.Capacity = 1,下次复用时可能因容量突降导致频繁扩容 - 不要把池化
StringBuilder当成万能药 ——new StringBuilder()本身几乎零分配(.NET 6+ 使用 stackalloc 优化),除非你每秒创建上万次且缓冲区 >4KB,否则池反而因线程安全开销更慢 - 真正该池化的,是那些
Create()成本高、可重置、且生命周期短的对象,比如含大数组的 DTO、临时加密上下文、自定义缓冲区包装类
最常被忽略的一点:Return() 不是“建议调用”,是契约义务。池不跟踪谁拿了对象,只认“有没有还”。漏一次,就少一个可用实例;错还两次,后续 Get() 可能拿到未重置的脏对象 —— 这种问题在线上压测时才暴露,但根源早在第一行 try 没包 finally 时就埋下了。


















