首頁  >  文章  >  後端開發  >  鎖定地圖並發訪問的地圖

鎖定地圖並發訪問的地圖

WBOY
WBOY轉載
2024-02-09 11:06:091070瀏覽

鎖定地圖並發訪問的地圖

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

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除