MST

星途 面试题库

面试题:Go每个请求一个goroutine时复杂数据结构及资源的并发安全管理

假设在Go的微服务架构中,每个请求由一个goroutine处理。存在一个复杂的数据结构,例如一个嵌套的结构体,内部包含多个子结构体和通道,用于协调不同模块间的通信。该数据结构需要在多个goroutine间共享和操作。同时,这些操作还涉及到外部资源(如数据库连接)的访问。请详细描述你会如何设计和实现这个系统,以确保整个系统在高并发场景下的并发安全,包括如何处理资源竞争、死锁预防等问题,并给出关键部分的代码框架及设计思路。
26.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 使用互斥锁(Mutex):对于共享的复杂数据结构,使用 sync.Mutex 来保护对其的读写操作,防止资源竞争。
  2. 数据库连接池:为了高效管理数据库连接,使用连接池,避免每次请求都创建新的连接,减少资源开销。
  3. 通道(Channel):利用通道来进行不同 goroutine 之间的通信,确保数据传递的有序性和安全性。
  4. 死锁预防:通过合理的资源获取顺序和避免循环依赖来预防死锁。在获取多个资源时,始终按照相同的顺序获取。

关键部分代码框架

package main

import (
    "database/sql"
    "fmt"
    "sync"

    _ "github.com/go-sql-driver/mysql" // 假设使用 MySQL 数据库
)

// 定义复杂的数据结构
type ComplexData struct {
    InnerStruct1 InnerStruct1
    InnerStruct2 InnerStruct2
    // 假设的通道用于模块间通信
    CommunicationChannel chan string
    mu sync.Mutex
}

type InnerStruct1 struct {
    // 具体字段
    Field1 string
}

type InnerStruct2 struct {
    // 具体字段
    Field2 int
}

// 数据库连接池
var db *sql.DB

func init() {
    var err error
    db, err = sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/database_name")
    if err != nil {
        panic(err.Error())
    }
    // 测试连接
    err = db.Ping()
    if err != nil {
        panic(err.Error())
    }
}

// 处理请求的函数
func handleRequest(data *ComplexData, requestID int) {
    data.mu.Lock()
    defer data.mu.Unlock()

    // 操作共享数据结构
    fmt.Printf("Handling request %d on shared data\n", requestID)

    // 从数据库连接池获取连接
    conn, err := db.Conn(nil)
    if err != nil {
        fmt.Printf("Error getting connection: %v\n", err)
        return
    }
    defer conn.Close()

    // 执行数据库操作
    rows, err := conn.Query("SELECT * FROM some_table")
    if err != nil {
        fmt.Printf("Error querying database: %v\n", err)
        return
    }
    defer rows.Close()

    // 处理数据库结果
    for rows.Next() {
        // 处理逻辑
    }
}

func main() {
    var wg sync.WaitGroup
    sharedData := ComplexData{
        CommunicationChannel: make(chan string),
    }

    // 模拟多个请求
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go func(id int) {
            defer wg.Done()
            handleRequest(&sharedData, id)
        }(i)
    }

    wg.Wait()
    close(sharedData.CommunicationChannel)
}

代码说明

  1. ComplexData 结构体:包含了内部子结构体以及一个通道,同时添加了 sync.Mutex 用于保护对该结构体的操作。
  2. 数据库连接池:通过 sql.Opendb.Ping 初始化数据库连接池。
  3. handleRequest 函数:使用互斥锁保护对共享数据结构的操作,从连接池获取数据库连接并执行数据库操作。
  4. main 函数:模拟多个请求,每个请求在一个新的 goroutine 中处理,并通过 sync.WaitGroup 等待所有请求处理完毕。