MST

星途 面试题库

面试题:Go语言并发安全的映射实现

Go语言的标准库`map`不是并发安全的。请设计一个并发安全的`map`数据结构,使用Go语言的并发特性(如互斥锁、读写锁、通道等),并提供`Set`(设置键值对)、`Get`(获取值)和`Delete`(删除键值对)方法,且需要说明不同锁策略在这个场景下的优缺点。
34.8万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
    "sync"
)

// SafeMap 并发安全的map结构体
type SafeMap struct {
    mu sync.RWMutex
    data map[interface{}]interface{}
}

// NewSafeMap 创建一个新的并发安全map
func NewSafeMap() *SafeMap {
    return &SafeMap{
        data: make(map[interface{}]interface{}),
    }
}

// Set 设置键值对
func (sm *SafeMap) Set(key, value interface{}) {
    sm.mu.Lock()
    defer sm.mu.Unlock()
    sm.data[key] = value
}

// Get 获取值
func (sm *SafeMap) Get(key interface{}) (interface{}, bool) {
    sm.mu.RLock()
    defer sm.mu.RUnlock()
    value, exists := sm.data[key]
    return value, exists
}

// Delete 删除键值对
func (sm *SafeMap) Delete(key interface{}) {
    sm.mu.Lock()
    defer sm.mu.Unlock()
    delete(sm.data, key)
}

锁策略优缺点

  1. 互斥锁(sync.Mutex
    • 优点:简单直接,能保证数据的一致性,任何时候只有一个goroutine可以读写map,避免了数据竞争。
    • 缺点:性能瓶颈明显,写操作会阻塞读操作,读操作也会阻塞写操作。在高并发读场景下,由于写操作的存在,读操作的性能会受到影响;在高并发写场景下,所有操作都会串行化,严重影响性能。
  2. 读写锁(sync.RWMutex
    • 优点:在读多写少的场景下性能较好,允许多个goroutine同时读,只有写操作时才会独占锁。读操作之间不会相互阻塞,提高了并发读的效率。
    • 缺点:写操作依然会阻塞所有读操作和其他写操作。在写多读少的场景下,性能提升不明显,甚至可能因为读写锁的管理开销而导致性能下降。而且读写锁的实现相对复杂,需要更仔细地考虑锁的使用顺序以避免死锁。
  3. 通道(chan
    • 优点:可以通过将读写操作封装成消息发送到通道,由专门的goroutine处理这些消息,实现数据的安全访问。这种方式能更好地控制并发逻辑,并且可以通过缓冲通道来优化性能。
    • 缺点:实现相对复杂,需要更多的代码来管理通道和处理消息。而且由于所有操作都通过通道传递,在高并发场景下,通道的缓冲管理和消息处理可能成为性能瓶颈。