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) } }
以上是锁定地图并发访问的地图的详细内容。更多信息请关注PHP中文网其他相关文章!