Go中map的读写操作分别如何加锁?为何使用读写锁?
1 个回答
你很远,也很近,在脑海,也在心里,唯独不在身边…冷月## 作用 - 保护多个 goroutine 共享的 `map`,避免并发读写导致数据竞争或运行时 panic,例如 `fatal error: concurrent map read and map write`。 - 使用 `sync.RWMutex` 可以在读多写少的场景下兼顾安全与性能。 ## 原理 ### 1. 读操作使用读锁 读取 map 时调用: - `RLock()`:获取读锁; - `RUnlock()`:释放读锁。 多个 goroutine 可以同时持有读锁并发读取,但读取期间不能有写入操作。 ```go func (m *MemoryCache) Get(key string) interface{} { m.rw.RLock() defer m.rw.RUnlock() if v, ok := m.c[key]; ok { return v.value } return nil } ``` ### 2. 写操作使用写锁 写入、修改、删除 map 时调用: - `Lock()`:获取写锁; - `Unlock()`:释放写锁。 写锁是独占锁:一个 goroutine 写入时,其他 goroutine 既不能读,也不能写。 ```go func (m *MemoryCache) Put(key string, expires int64, value interface{}) { m.rw.Lock() defer m.rw.Unlock() m.c[key] = &MemoryCacheValue{ value: value, expires: time.Now().Unix() + expires, } } ``` ### 3. 为什么使用读写锁 - 普通互斥锁会让所有读操作也互相阻塞; - `RWMutex` 允许多个读操作并发执行; - 写操作仍然独占执行,从而保证 map 的一致性; - 因此适合“读多写少”的并发场景。 ### 4. 注意事项 - 只要 map 存在被并发写入的可能,所有读操作也必须加锁,不能认为“只读就是安全的”。 - 要及时释放锁,通常配合 `defer` 使用。 - 不要在锁内执行网络请求、文件 I/O 等耗时操作。 - 遍历 map 时也应全程持锁;如需复制,应在锁内完成。发布于 2026-10-26 06:31 •IP属地 北京举报评论收藏
公众号进入网站体验更佳

