php小编百草在这里向大家介绍一种非常有用的技巧,即锁定地图并发访问的地图。这个技巧可以帮助开发者在并发访问地图时避免冲突和数据错误。通过使用锁定机制,开发者可以确保每个请求都能按顺序进行,并且不会出现数据混乱的情况。这对于开发中的地图操作非常重要,特别是在多个用户同时访问地图时。下面让我们一起来了解一下如何实现这个技巧吧!
问题内容
我有一个地图:map[string]map[string]*Struct,我需要在多个 Go 例程中读取/写入它。
实现这一目标的最佳方法是什么?互斥体或 RWMutex ?以及放置在哪里?
如果我使用 RWMutex,那么在执行涉及读和写的操作之前我应该锁定还是 RLock?
我尝试在根映射中使用 rwmutex,但我不确定这是否是解决此问题的最佳方法。
我还尝试在读写之前“锁定”,但有时会收到“并发写入”恐慌。
解决方法
您可以使用RWLock。如果操作涉及到写(不管是读还是只写)就需要使用Lock,如果只涉及读则RLock/RUnlock。
Lock也可以被认为是独占锁。另一方面,RLock 是非排他性的。 即使 RWMutex 已被锁定以进行读取,也可以获取 RLock,但如果资源被 Lock 方法独占锁定,则会阻止 goroutine 执行:
a blocked Lock call excludes new readers from acquiring the lock
另一方面,Lock 方法会阻止 goroutine 执行,直到所有读取器和写入器解锁资源(使用 RUnlock/Unlock 方法)。 Lock 是独占的,因为在调用 Unlock 方法之前,只有一个 goroutine 可以访问资源(无论是读还是写)。
典型方法:
package main
import (
"fmt"
"sync"
)
type SomeStruct struct {
someInfo string
}
type ConcurrentStruct struct {
mu sync.RWMutex
data map[string]map[string]*SomeStruct
}
func New() *ConcurrentStruct {
return &ConcurrentStruct{
data: make(map[string]map[string]*SomeStruct),
}
}
func (cs *ConcurrentStruct) Set(key1, key2 string, val SomeStruct) {
cs.mu.Lock()
defer cs.mu.Unlock()
if _, ok := cs.data[key1]; !ok {
cs.data[key1] = make(map[string]*SomeStruct)
}
cs.data[key1][key2] = &val
}
func (cs *ConcurrentStruct) Get(key1, key2 string) (val *SomeStruct, ok bool) {
cs.mu.RLock()
defer cs.mu.RUnlock()
if _, ok := cs.data[key1]; ok {
val, ok := cs.data[key1][key2]
return val, ok
}
return nil, false
}
func main() {
cs := New()
cs.Set("a", "b", SomeStruct{"Hello, World!"})
if _, ok := cs.Get("a", "c"); !ok {
fmt.Printf("key1=a, key2=c, not found\n")
}
if s, ok := cs.Get("a", "b"); ok {
fmt.Printf("key1=a, key2=b, found: %v\n", s)
}
}
以上就是锁定地图并发访问的地图的详细内容,更多请关注编程网其它相关文章!