面试题答案
一键面试- 关键步骤:
- 使用
sync.WaitGroup
来等待所有的 goroutine 完成。 - 使用
sync.Mutex
来保护对信号量计数器的访问。 - 定义一个代表信号量的计数器,每次获取信号量时计数器减一,释放信号量时计数器加一。
- 使用
- 代码示例:
package main
import (
"fmt"
"sync"
)
// Semaphore结构体用于实现信号量
type Semaphore struct {
count int
mutex sync.Mutex
cond sync.Cond
}
// NewSemaphore创建一个新的信号量实例
func NewSemaphore(count int) *Semaphore {
s := &Semaphore{
count: count,
}
s.cond.L = &s.mutex
return s
}
// Acquire获取一个信号量
func (s *Semaphore) Acquire() {
s.mutex.Lock()
for s.count <= 0 {
s.cond.Wait()
}
s.count--
s.mutex.Unlock()
}
// Release释放一个信号量
func (s *Semaphore) Release() {
s.mutex.Lock()
s.count++
s.cond.Broadcast()
s.mutex.Unlock()
}
func main() {
// 创建一个信号量,允许最多3个并发访问
semaphore := NewSemaphore(3)
var wg sync.WaitGroup
// 模拟10个并发任务
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
semaphore.Acquire()
defer semaphore.Release()
fmt.Printf("Goroutine %d is accessing the resource\n", id)
// 模拟对数据库连接池等资源的访问
}(i)
}
wg.Wait()
}
在上述代码中:
Semaphore
结构体包含一个计数器count
用于表示可用的信号量数量,一个sync.Mutex
用于保护对count
的访问,以及一个sync.Cond
用于等待信号量可用。NewSemaphore
函数用于初始化信号量,设置初始的信号量数量。Acquire
方法用于获取一个信号量,如果信号量不足则等待。Release
方法用于释放一个信号量,并通知等待的 goroutine。- 在
main
函数中,创建了一个允许最多3个并发访问的信号量,并启动10个 goroutine 来模拟对资源的并发访问。每个 goroutine 在访问资源前先获取信号量,访问结束后释放信号量。