Tip #77 带缓冲的 channel 作为信号量来限制 goroutine 执行

原始链接:Golang Tip #77: Buffered channels as semaphores to limit goroutine execution

当我们想要管理有多少 goroutine 可以同时访问一个资源时,使用信号量是一种可靠的方法。

我们可以使用带有缓冲的 channel 来创建信号量,channel 的大小决定了可以同时运行多少个 goroutine:

tips077-img1

接下来:

  • 一个 goroutine 将一个值发送到 channel 中,占据一个槽位
  • 在完成任务后移除该值,从而为另一个 goroutine 释放该槽位

tips077-img2

在这个例子中:

  • wg.Add(10) 指我们准备用 10 个 goroutine 来完成所有工作
  • make(chan struct{}, 3) 设置了一个只允许 3 并发的有缓冲 channel 作为信号量

如果想更简洁的实现,我们可以考虑创建一个 Semaphore 类型来处理信号量相关的操作:

tips077-img3

使用这个自定义的 Semaphore 类型简化了对资源访问的控制:

tips077-img4

此外,golang.org/x/sync/semaphore... 包中提供了一个信号量的实现,是加权信号量。

加权信号量允许一个 goroutine 占用多个槽位,适用于每个 goroutine 资源消耗不同的情况。

例如,管理数据库的连接池时,某些操作可能需要一次使用多个连接。