sync.Map LoadOrStore 是否会受到竞争条件的影响?

问题描述 投票:0回答:1

我在 Go 中使用

sync.Map
LoadOrStore
方法。我试图了解是否可能存在竞争条件导致对价值创造函数进行多次评估。我试图了解这是否准确以及如何正确处理。

package main

import (
    "fmt"
    "sync"
)

type HashIDMap struct {
    m sync.Map
}

func (hm *HashIDMap) GetOrCreate(key, value string, createFunc func(string, string)) string {
    actual, loaded := hm.m.LoadOrStore(key, value)
    if !loaded {
        // If the value was not loaded, it means we stored it and need to create the database entry
        createFunc(key, value)
    }
    return actual.(string)
}

func createDatabaseEntry(key, value string) {
    // Simulate database entry creation
    fmt.Printf("Creating database entry for key: %s with value: %s\n", key, value)
}

func main() {
    hm := &HashIDMap{}

    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        defer wg.Done()
        id := hm.GetOrCreate("hash_1", "id_1", createDatabaseEntry)
        fmt.Println("Goroutine 1 got ID:", id)
    }()

    go func() {
        defer wg.Done()
        id := hm.GetOrCreate("hash_1", "id_1", createDatabaseEntry)
        fmt.Println("Goroutine 2 got ID:", id)
    }()

    wg.Wait()
}

我读过一些建议,由于竞争条件,

createFunc
实际上可能被执行多次。

根据我的理解,这正是

LoadOrStore
想要解决的问题,但现在我不再有信心竞争条件是否真的可能。

同一键是否可以调用两次

createDatabaseEntry

go concurrency synchronization
1个回答
0
投票

它不会产生竞争条件。您读到的建议是错误的。

sync.Map
的文档指出(强调我的):

用Go内存模型的术语来说,Map安排写操作“同步在”任何观察写效果的读操作之前,其中读操作和写操作定义如下。 Load、LoadAndDelete、LoadOrStore、Swap、CompareAndSwap、CompareAndDelete是读操作; Delete、LoadAndDelete、Store、Swap是写操作; LoadOrStore 当返回loaded设置为false时是一个写操作

因此,正如预期的那样,对返回

LoadOrStore
(写操作)的
false
的调用保证发生在返回
LoadOrStore
(读操作)的
true
之前。

© www.soinside.com 2019 - 2024. All rights reserved.