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中文網其他相關文章!