Golang如何使用信号量进行Goroutine的同步?

使用信号量可以对一组资源进行访问控制,对于 Go 语言而言,通常使用 sync 包中的 Semaphore 类型来实现信号量。Semaphore 的定义如下:

type Semaphore struct {
    ch chan struct{}
}

func NewSemaphore(n int) *Semaphore {
    return &Semaphore{make(chan struct{}, n)}
}

func (s *Semaphore) Acquire() {
    s.ch <- struct{}{}
}

func (s *Semaphore) Release() {
    <-s.ch
}

Semaphore 的 Acquire 方法用于获取资源,如果没有可用资源,则会阻塞直到有资源可用;Release 方法用于释放资源。下面是一个示例,演示如何使用 Semaphore 控制并发执行:

var sem = NewSemaphore(3)

func main() {
    for i := 0; i < 10; i++ {
        go func(n int) {
            sem.Acquire()
            defer sem.Release()
            fmt.Printf("start task %d\n", n)
            time.Sleep(time.Second)
            fmt.Printf("finish task %d\n", n)
        }(i)
    }

    time.Sleep(time.Second * 5)
}

在这个示例中,Semaphore 的容量为 3,因此最多同时执行 3 个任务。每个任务在开始时先调用 Acquire 方法获取资源,结束时再调用 Release 方法释放资源。在主函数中,我们让程序休眠 5 秒钟,以确保所有任务都有机会执行完毕。