Карта / массив одновременного доступа Golang с фиксированным размером - PullRequest
0 голосов
/ 30 августа 2018

Я изучал возможность одновременного доступа к карте с фиксированными ключами без блокировки для повышения производительности. Я исследовал подобное с ломтик раньше и, кажется, он работает:

func TestConcurrentSlice(t *testing.T) {
    fixed := []int{1, 2, 3}
    wg := &sync.WaitGroup{}
    for i := 0; i < len(fixed); i++ {
        idx := i
        wg.Add(1)
        go func() {
            defer wg.Done()
            fixed[idx]++
        }()
    }
    wg.Wait()
    fmt.Printf("%v\n", fixed)
}

Приведенный выше код пройдет тест -race.

Это дало мне уверенность в достижении того же самого с картой с фиксированным размером (фиксированное количество ключей), потому что я предполагаю, что если количество ключей не меняется, то массив подчеркивания (на карте) расширять не нужно Таким образом, для нас будет безопасно обращаться к разным ключам (разным ячейкам памяти) в разных подпрограммах. Итак, я написал этот тест:

type simpleStruct struct {
    val int
}

func TestConcurrentAccessMap(t *testing.T) {
    fixed := map[string]*simpleStruct{
        "a": {0},
        "b": {0},
    }
    wg := &sync.WaitGroup{}
    // here I use array instead of iterating the map to avoid read access
    keys := []string{"a", "b"}
    for _, k := range keys {
        kcopy := k
        wg.Add(1)
        go func() {
            defer wg.Done()
            // this failed the race test
            fixed[kcopy] = &simpleStruct{}

            // this actually can pass the race test!
            //fixed[kcopy].val++
        }()
    }
    wg.Wait()
}

однако тест не прошел гоночный тест с одновременной записью сообщения об ошибке функцией runtime.mapassign_faststr ().

И еще один интересный момент, который я нашел, - это код, который я закомментировал: «fixed [kcopy] .val ++» фактически прошел гоночный тест (я полагаю, это из-за того, что записи находятся в разных местах памяти). Но мне интересно, так как стандартные программы получают доступ к различным ключам карты, почему он не пройдет гоночный тест?

1 Ответ

0 голосов
/ 30 августа 2018

Доступ к различным элементам среза без синхронизации из нескольких процедур - это нормально, поскольку каждый элемент среза действует как отдельная переменная. Подробнее см. Могу ли я одновременно писать разные элементы среза .

Однако с картами дело обстоит иначе. Значение для конкретного ключа не действует как переменная, и оно не адресуется (поскольку фактическое пространство памяти, в котором хранится значение, может быть внутренне изменено - по собственному усмотрению реализации).

То же самое относится и к картам: применяется общее правило: если к карте обращаются из нескольких программ, где хотя бы одна из них является записью (присваивает значение ключу), необходима явная синхронизация.

...