我有一张Map:map[string]map[string]* 我需要在多个Go例程中读/写的结构。实现这一目标的最佳途径是什么?Mutex还是RWMutex?放在哪里如果我使用RWMutex,那么我应该在做一个涉及读和写的操作之前锁定还是锁定?我试着在根Map中有一个rwmutex,但我不确定这是否是解决这个问题的最佳方法。另外,我试图“锁定”之前读和写,但我收到“并发写”恐慌有时。
6pp0gazn1#
您可以使用RWLock。如果操作涉及到写(不管是读还是写),你需要使用锁,如果只有读,那么使用RLock/RUnlock。锁也可以被认为是排他性的锁。另一方面,RLock是非排他性的。即使RWMutex已经被锁定阅读,也可以获取RLock,但是如果资源被Lock方法独占锁定,则会阻止goroutine执行:
a blocked Lock call excludes new readers from acquiring the lock
另一方面,Lock方法阻止goroutine执行,直到所有的读写器解锁资源(使用RUnlock/Unlock方法)。Lock是独占的,因为只有一个goroutine可以访问资源(无论是阅读还是写),直到Unlock方法被调用。典型方法:
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) } }
1条答案
按热度按时间6pp0gazn1#
您可以使用RWLock。如果操作涉及到写(不管是读还是写),你需要使用锁,如果只有读,那么使用RLock/RUnlock。
锁也可以被认为是排他性的锁。另一方面,RLock是非排他性的。即使RWMutex已经被锁定阅读,也可以获取RLock,但是如果资源被Lock方法独占锁定,则会阻止goroutine执行:
另一方面,Lock方法阻止goroutine执行,直到所有的读写器解锁资源(使用RUnlock/Unlock方法)。Lock是独占的,因为只有一个goroutine可以访问资源(无论是阅读还是写),直到Unlock方法被调用。
典型方法: