Я изучал возможность одновременного доступа к карте с фиксированными ключами без блокировки для повышения производительности.
Я исследовал подобное с ломтик раньше и, кажется, он работает:
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 ++» фактически прошел гоночный тест (я полагаю, это из-за того, что записи находятся в разных местах памяти). Но мне интересно, так как стандартные программы получают доступ к различным ключам карты, почему он не пройдет гоночный тест?