首頁 > 後端開發 > Golang > 並發讀寫Go結構體時如何防止資料爭用?

並發讀寫Go結構體時如何防止資料爭用?

Mary-Kate Olsen
發布: 2024-12-25 04:21:09
原創
550 人瀏覽過

How Can I Prevent Data Races When Concurrently Reading and Writing Go Structs?

在沒有明確鎖定的情況下並發讀寫 Go 結構

並發存取 Go 中的共享資料可能是潛在錯誤的來源,例如資料爭用。當對資料結構的存取是並發的,即多個 goroutine 可以同時存取它時,確保資料的讀寫同步以避免不一致是至關重要的。

結構體的同時存取

考慮以下Go struct 元資料:

type Metadata struct {
    mu  sync.RWMutex // ?
    key bool
}
登入後複製

如我們所見,元資料結構體包含一個bool 類型的欄位key 和另一個sync.RWMutex 類型的欄位mu,它是讀寫鎖的實作。

結構體中的資料爭用

如果我們建立一個 Metadata 實例並允許多個 goroutine 同時讀寫它的字段,我們可能會遇到資料競爭。當多個 Goroutines 並發存取相同的資料並且至少其中一個正在執行寫入操作時,就會發生資料競爭。

以下程式碼示範了在沒有明確鎖定的情況下對Metadata 結構體的並發讀寫存取:

func concurrentStruct() {
    m := new(Metadata)

    for i := 0; i < 100000; i++ {
        go func(metadata *Metadata) {
            for {
                readValue := metadata.key
                if readValue {
                    metadata.key = false
                }
            }
        }(m)

        go func(metadata *Metadata) {
            for {
                metadata.key = true
            }
        }(m)
    }

    select {}
}
登入後複製

在這段程式碼中,我們建立了一個並發讀取和寫入關鍵字段的goroutine。我們使用 select 語句來阻止主 goroutine,從而允許並發 goroutine 運行。使用 go run -race 指令執行程序,我們會收到一則警告,指出出現了 DATA RACE。

但是,程式繼續運行,沒有崩潰。這是因為Go運行時有內建的並發檢查,但它不能保證安全執行。在這種情況下,資料爭用可能會導致未定義的行為和不正確的結果。

解決結構中的資料爭用

為了防止並發讀取和寫入結構時出現資料爭用,我們需要使用正確的方法鎖定機制。一種方法是使用互斥鎖,如以下程式碼所示:

func concurrentStructWithMuLock() {
    m := new(Metadata)

    go func(metadata *Metadata) {
        for {
            metadata.mu.Lock()
            readValue := metadata.key
            if readValue {
                metadata.key = false
            }
            metadata.mu.Unlock()
        }
    }(m)

    go func(metadata *Metadata) {
        for {
            metadata.mu.Lock()
            metadata.key = true
            metadata.mu.Unlock()
        }
    }(m)

    select {}
}
登入後複製

在此程式碼中,我們向元資料結構添加了讀寫鎖,並使用 mu.Lock() 和 mu。 Unlock() 同步對關鍵字段的存取。使用 go run -race 執行程式將不再產生任何警告,表示不存在資料爭用。

以上是並發讀寫Go結構體時如何防止資料爭用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板