侧边栏壁纸
博主头像
colo

欲买桂花同载酒

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

实现并发安全的资源池管理

2025-12-11 / 0 评论 / 7 阅读

题目

实现并发安全的资源池管理

信息

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

考点

channel缓冲机制, select超时控制, 并发资源管理, 错误处理

快速回答

实现要点:

  • 使用带缓冲的channel作为资源池容器
  • 通过select实现超时控制防止死锁
  • 使用sync.Once确保资源关闭安全性
  • 处理获取资源时的错误场景
## 解析

问题场景

设计一个数据库连接池,要求:

  1. 支持并发获取/释放连接
  2. 获取连接时支持超时控制
  3. 连接耗尽时阻塞等待直到有资源释放
  4. 安全关闭资源池并处理残留请求

解决方案

type Pool struct {
    resources chan *Resource
    closed    bool
    closeOnce sync.Once
    closeChan chan struct{}
}

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

func (p *Pool) Acquire(timeout time.Duration) (*Resource, error) {
    select {
    case res := <-p.resources:
        return res, nil
    case <-time.After(timeout):
        return nil, errors.New("timeout")
    case <-p.closeChan:
        return nil, errors.New("pool closed")
    }
}

func (p *Pool) Release(res *Resource) {
    select {
    case p.resources <- res: // 正常归还
    case <-p.closeChan: // 资源池已关闭
        res.Close() // 直接销毁资源
    }
}

func (p *Pool) Close() {
    p.closeOnce.Do(func() {
        close(p.closeChan)  // 通知所有协程
        close(p.resources)  // 关闭channel
        for res := range p.resources { // 清理残留资源
            res.Close()
        }
    })
}

核心原理

  • 缓冲channel:固定容量的channel模拟资源池,长度即最大连接数
  • select多路复用:同时监听资源获取、超时和关闭信号
  • sync.Once:确保关闭操作只执行一次,避免panic
  • 双通道关闭:closeChan通知释放协程立即终止,resources通道关闭触发资源清理

最佳实践

  1. 使用make(chan T, size)创建缓冲通道作为容器
  2. 在Acquire中使用time.After实现超时控制
  3. Release时检查关闭状态,避免向已关闭channel发送数据
  4. Close方法中先关闭通知通道,再处理资源通道

常见错误

错误示例后果修复方案
未处理超时高并发时永久阻塞select+time.After
重复关闭channel运行时panicsync.Once保护
关闭后归还资源send on closed channelRelease中检查closeChan

扩展知识

  • 泄漏风险:goroutine阻塞在channel操作时,需通过context实现级联取消
  • 动态扩容:结合sync.Mutex和条件变量实现弹性资源池
  • 健康检查:在Release时验证资源有效性,销毁不可用资源
  • atomic优化:使用atomic.Bool替代closed bool标志避免数据竞争