功能说明
WeightedSemaphore 用互斥锁和条件变量限制并发工作的总权重。每个任务按自身成本调用 Acquire,容量不足时在条件变量上等待;Release 归还权重并广播唤醒所有等待者。等待期间会监听上下文取消,通过一个辅助 goroutine 在取消时广播,让 Acquire 能及时返回。
关键代码
for s.used+weight > s.capacity {
if err := ctx.Err(); err != nil {
return err
}
s.cond.Wait()
}
if err := ctx.Err(); err != nil {
return err
}
s.used += weight
cond.Wait() 会原子地释放锁并阻塞,被唤醒后重新加锁,因此循环里必须再次检查条件。
使用注意
- 条件变量不保证公平,大权重任务可能长期等不到足够空间。
- 权重必须大于 0 且不超过总容量,否则请求永远无法满足。
Release传入的权重不能超过当前占用量,示例用 panic 暴露调用错误。- 取消监听 goroutine 在正常返回时通过
close(done)退出,避免泄漏。 - 该实现只在单进程内有效,跨实例限流需要集中式存储。
验证方式
示例容量为 3,四个任务权重分别为 1、2、3、1,应全部在超时前完成并打印 all jobs done。把某个任务权重改为 4 可验证参数错误;把上下文超时改为 1 毫秒可观察等待被取消。