使用互斥锁
互斥锁是一种最常见且简单的控制并发访问的方法。在访问map之前,先获取互斥锁,在访问完毕后释放锁。这样可以确保同一时间只有一个线程在访问map,避免了并发写导致的数据竞争。示例代码:
import "sync"
var m map[string]int
var lock sync.Mutex
func main() {
m = make(map[string]int)
// 设置值
lock.Lock()
m["key"] = 1
lock.Unlock()
// 获取值
lock.Lock()
value := m["key"]
lock.Unlock()
// ...
}
使用读写锁
如果有很多线程只是读取map的值而没有修改操作,那么使用互斥锁可能会导致性能问题。这时可以使用读写锁(sync.RWMutex),它支持多个读操作和单个写操作。示例代码:
import "sync"
var m map[string]int
var rwLock sync.RWMutex
func main() {
m = make(map[string]int)
// 读操作
rwLock.RLock()
value := m["key"]
rwLock.RUnlock()
// 写操作
rwLock.Lock()
m["key"] = 1
rwLock.Unlock()
// ...
}
使用并发安全的Map实现
除了使用锁来控制并发访问,还可以使用一些已经被证实在并发环境中安全的Map实现,如sync.Map。sync.Map是Golang标准库提供的一种线程安全的Map实现,可以在并发环境中安全地进行读写操作,而无需额外的锁。示例代码:
import "sync"
var m sync.Map
func main() {
// 写操作
m.Store("key", 1)
// 读操作
value, ok := m.Load("key")
if ok {
// ...
}
// ...
}