MST

星途 面试题库

面试题:Go语言中如何使用信号量来限制并发访问资源

假设你有一个需要限制并发访问的资源,例如数据库连接池,在Go语言中你如何使用信号量机制来实现对该资源的并发访问控制?请给出简要的代码示例并解释关键步骤。
34.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 关键步骤
    • 使用 sync.WaitGroup 来等待所有的 goroutine 完成。
    • 使用 sync.Mutex 来保护对信号量计数器的访问。
    • 定义一个代表信号量的计数器,每次获取信号量时计数器减一,释放信号量时计数器加一。
  2. 代码示例
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 在访问资源前先获取信号量,访问结束后释放信号量。