并发安全 Map
难度:⭐⭐⭐ 困难
考点
- map 并发不安全的原因
- 用 sync.RWMutex 保护 map
- 读写锁与互斥锁的选择
题目描述
实现一个并发安全的泛型 Map,支持基本的 CRUD 操作。
要求:
- 支持 Set、Get、Delete、Len 操作
- Get 操作返回 (value, bool),bool 表示 key 是否存在
- 使用读写锁(RWMutex)优化读多写少场景
- 额外实现 Range 方法,安全地遍历所有 kv 对
函数签名
go
type SafeMap struct { ... }
func NewSafeMap() *SafeMap
func (m *SafeMap) Set(key string, value int)
func (m *SafeMap) Get(key string) (int, bool)
func (m *SafeMap) Delete(key string)
func (m *SafeMap) Len() int
func (m *SafeMap) Range(fn func(key string, value int) bool)提示
- RWMutex:读操作用 RLock/RUnlock,写操作用 Lock/Unlock
- Range 回调返回 false 时应停止遍历
- Range 遍历期间持有读锁,回调中不要调用写操作(会死锁)
参考答案(Go)
点击展开参考答案
go
//go:build ignore
package answer
import "sync"
type SafeMap struct {
mu sync.RWMutex
data map[string]int
}
func NewSafeMap() *SafeMap {
return &SafeMap{
data: make(map[string]int),
}
}
func (m *SafeMap) Set(key string, value int) {
m.mu.Lock()
defer m.mu.Unlock()
m.data[key] = value
}
func (m *SafeMap) Get(key string) (int, bool) {
m.mu.RLock()
defer m.mu.RUnlock()
v, ok := m.data[key]
return v, ok
}
func (m *SafeMap) Delete(key string) {
m.mu.Lock()
defer m.mu.Unlock()
delete(m.data, key)
}
func (m *SafeMap) Len() int {
m.mu.RLock()
defer m.mu.RUnlock()
return len(m.data)
}
func (m *SafeMap) Range(fn func(key string, value int) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
for k, v := range m.data {
if !fn(k, v) {
break
}
}
}