侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

设计一个并发安全的资源池(Pool)

2025-12-12 / 0 评论 / 4 阅读

题目

设计一个并发安全的资源池(Pool)

信息

  • 类型:问答
  • 难度:⭐⭐

考点

并发控制,资源管理,接口设计,错误处理

快速回答

实现一个并发安全的资源池需要关注以下要点:

  • 使用 sync.Mutexsync.RWMutex 保护共享状态
  • 通过 context.Context 实现超时控制
  • 使用带缓冲的 channel 管理资源
  • 处理资源创建失败和池关闭场景
  • 提供 Get()Put() 接口并处理资源回收
## 解析

问题背景

在高并发场景中,频繁创建/销毁资源(如数据库连接、网络连接)会导致性能瓶颈。资源池通过复用资源减少开销,但需保证并发安全性和资源有效性。

核心实现方案

type Pool struct {
    resources chan Resource
    factory   func() (Resource, error)
    mu        sync.Mutex
    closed    bool
}

func NewPool(factory func() (Resource, error), size int) *Pool {
    p := &Pool{
        resources: make(chan Resource, size),
        factory:   factory,
    }
    // 预初始化资源
    for i := 0; i < size; i++ {
        res, _ := factory()
        p.resources <- res
    }
    return p
}

func (p *Pool) Get(ctx context.Context) (Resource, error) {
    select {
    case res := <-p.resources:
        return res, nil
    case <-ctx.Done():
        return nil, ctx.Err()
    default:
        // 无可用资源时创建新资源
        return p.factory()
    }
}

func (p *Pool) Put(res Resource) {
    p.mu.Lock()
    defer p.mu.Unlock()

    if p.closed {
        res.Close() // 池已关闭时释放资源
        return
    }

    select {
    case p.resources <- res: // 放回资源
    default:
        res.Close() // 池满时释放资源
    }
}

func (p *Pool) Close() {
    p.mu.Lock()
    defer p.mu.Unlock()

    if p.closed {
        return
    }
    p.closed = true
    close(p.resources)
    for res := range p.resources {
        res.Close()
    }
}

关键设计点

  • 并发控制
    • 使用 sync.Mutex 保护 closed 状态
    • 通过带缓冲的 channel 实现资源队列(线程安全)
  • 资源管理
    • Get() 优先从 channel 获取资源,无资源时调用 factory 创建
    • Put() 检查池状态,池满或关闭时释放资源
  • 超时控制
    • Get() 使用 context.Context 支持超时取消
  • 关闭处理
    • Close() 方法安全释放所有资源并标记状态
    • 禁止关闭后继续操作

最佳实践

  • 资源健康检查:在 Put() 时检测资源有效性,丢弃无效资源
  • 动态扩容:记录创建的资源数量,限制最大资源数
  • 泄漏防护:为资源添加最后使用时间戳,定期清理闲置资源

常见错误

  • 竞态条件:未对 closed 状态加锁导致数据竞争
  • 资源泄漏Get() 创建新资源后未在 Put() 中正确回收
  • 死锁风险factory 函数阻塞且无超时控制
  • 无效资源:未检查放回资源是否已关闭

扩展知识

  • 标准库参考sync.Pool 适用于临时对象池,但无状态管理
  • 连接池优化database/sql 的连接池实现(最大打开数/最大闲置数)
  • 高级模式
    • 资源借用统计(如 Prometheus 指标)
    • 基于权重的资源分配
    • 故障资源自动剔除