Нужен ли syn c .Mutex при доступе к разным полям одной и той же структуры, но в отдельных подпрограммах? - PullRequest
0 голосов
/ 11 апреля 2020

У меня есть структура, в которой есть несколько простых полей (ie: int, string и [] byte).

У меня также есть несколько процедур, которые изменяют различные поля в структуре. Но каждая программа изменяет свое поле.

Я не заметил никаких проблем или намеков на условия гонки. Затем я довольно легко добавил syn c .Mutex в код, и код работал точно так же.

Но из того, что я прочитал, некоторые могут предложить использовать syn c .Mutex в эта ситуация. Нужно ли это, хотя программа работает без ошибок?

1 Ответ

0 голосов
/ 11 апреля 2020

Обрабатывать каждое поле структуры как независимое с целью блокировки. Дано:

type Foo struct {
    stringMap  map[string]string
    strings   []string
    numbers   []float64
}

Следующее безопасно:

foo := &Foo{}
/* ... */
go func() {
    foo.stringMap["foo"] = "bar"
}()
go func() {
    foo.strings[0] = "baz"
}()
go func() {
    fmt.Println(foo.numbers[0])
}()

Но это небезопасно:

go func() {
    fmt.Println(foo.numbers[0])
}()
go func() {
    foo.numbers = append(foo.numbers, 123.456)
}()

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

type Foo struct {
    stringMapMu sync.Mutex
    stringMap   map[string]string
    stringsMu   sync.Mutex
    strings     []string
    numbersMu   sync.Mutex
    numbers     []float64
}

Тогда:

go func() {
    foo.numbersMu.Lock()
    defer foo.numbersMu.Unlock()
    fmt.Println(foo.numbers[0])
}()
go func() {
    foo.numbersMu.Lock()
    defer foo.numbersMu.Unlock()
    foo.numbers = append(foo.numbers, 123.456)
}()
...