MST
星途 面试题库

面试题:Go中如何使用信号量控制并发访问数据库连接

假设你有一个数据库连接池,为了避免过多的并发连接对数据库造成压力,需要使用信号量来限制同时能够使用的连接数。请编写一段Go代码,展示如何使用信号量实现这一功能。说明信号量的初始化以及在获取和释放连接时信号量的操作。
23.9万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "sync"
    "time"
)

// 数据库连接池结构体
type ConnectionPool struct {
    pool     chan struct{}
    maxConns int
}

// 创建新的数据库连接池
func NewConnectionPool(maxConns int) *ConnectionPool {
    return &ConnectionPool{
        pool:     make(chan struct{}, maxConns),
        maxConns: maxConns,
    }
}

// 获取一个数据库连接
func (cp *ConnectionPool) GetConnection() {
    cp.pool <- struct{}{} // 获取信号量
}

// 释放一个数据库连接
func (cp *ConnectionPool) ReleaseConnection() {
    <-cp.pool // 释放信号量
}

func main() {
    maxConns := 3
    cp := NewConnectionPool(maxConns)

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            cp.GetConnection()
            fmt.Printf("Goroutine %d got connection\n", id)
            time.Sleep(time.Second) // 模拟数据库操作
            fmt.Printf("Goroutine %d released connection\n", id)
            cp.ReleaseConnection()
        }(i)
    }
    wg.Wait()
}
  1. 信号量初始化
    • pool 是一个带缓冲的通道,其缓冲大小 maxConns 就是信号量的数量,以此来限制同时能获取的连接数。
  2. 获取连接
    • GetConnection 方法通过向 pool 通道发送一个空结构体来获取信号量,若通道已满(即达到最大连接数),则会阻塞,直到有连接被释放。
  3. 释放连接
    • ReleaseConnection 方法通过从 pool 通道接收一个空结构体来释放信号量,使得其他等待的 goroutine 可以获取连接。