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