← 中文资源

简体中文版本

适合变成本任务的加权信号量

用互斥锁与条件变量实现加权信号量,按任务权重占用容量,支持上下文取消等待,释放时广播唤醒其他等待者。

阅读英文原文

功能说明

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 毫秒可观察等待被取消。