面试题答案
一键面试基本思路
在Go语言中,信号量可以通过 sync.WaitGroup
和通道(channel
)来模拟实现。基本思路是利用一个带缓冲的通道来表示可用的资源数量,每个协程在开始时尝试从通道获取一个信号(如果通道已满则阻塞等待),完成任务后将信号放回通道,以此来控制同时运行的协程数量。
示例代码
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
semaphore := make(chan struct{}, 5)
for i := 0; i < 10; i++ {
wg.Add(1)
semaphore <- struct{}{}
go func(id int) {
defer func() {
<-semaphore
wg.Done()
}()
fmt.Printf("协程 %d 开始执行\n", id)
time.Sleep(1 * time.Second)
fmt.Printf("协程 %d 执行结束\n", id)
}(i)
}
wg.Wait()
}
在上述代码中:
- 定义了一个带缓冲为5的通道
semaphore
作为信号量。 - 在启动每个协程前,向
semaphore
通道发送一个空结构体,若通道已满则会阻塞,从而限制并发数量。 - 在协程结束时,从
semaphore
通道接收一个空结构体,将信号量归还,使得其他协程可以获取信号量继续执行。 - 使用
sync.WaitGroup
来等待所有协程执行完毕。