MST

星途 面试题库

面试题:Go信号量在复杂数据结构操作中的线程安全应用

假设有一个复杂的数据结构,例如一个嵌套的map结构,其中每个内层map都关联了一些资源。现在需要在多个协程中对这个数据结构进行读写操作,如何使用Go信号量来确保这些操作的线程安全,同时尽量减少锁争用,提高程序性能?请给出具体的实现思路和关键代码片段。
37.3万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试

实现思路

  1. 信号量设计:使用 sync/semaphore 包中的 Weighted 类型来创建信号量。信号量的权重决定了同一时间能够访问共享资源(嵌套 map 结构)的最大协程数。通过合理设置权重,可以平衡并发度和锁争用。
  2. 读写操作:在进行读写操作前,先获取信号量。读取操作完成后释放信号量,写入操作完成后同样释放信号量。这样可以确保在同一时间只有一定数量的协程可以访问共享数据结构,减少锁争用。

关键代码片段

package main

import (
    "fmt"
    "sync"
    "sync/semaphore"
)

var (
    data     = make(map[string]map[string]interface{})
    sem      = semaphore.NewWeighted(5) // 设置同一时间最多5个协程访问
    mu       sync.Mutex
)

// 读取数据
func read(key1, key2 string) (interface{}, bool) {
    err := sem.Acquire(nil, 1)
    if err != nil {
        fmt.Println("获取信号量失败:", err)
        return nil, false
    }
    defer sem.Release(1)

    mu.Lock()
    innerMap, ok := data[key1]
    if ok {
        value, ok := innerMap[key2]
        mu.Unlock()
        return value, ok
    }
    mu.Unlock()
    return nil, false
}

// 写入数据
func write(key1, key2 string, value interface{}) {
    err := sem.Acquire(nil, 1)
    if err != nil {
        fmt.Println("获取信号量失败:", err)
        return
    }
    defer sem.Release(1)

    mu.Lock()
    if _, ok := data[key1];!ok {
        data[key1] = make(map[string]interface{})
    }
    data[key1][key2] = value
    mu.Unlock()
}