Несколько мьютексов в одной структуре? - PullRequest
0 голосов
/ 14 февраля 2019

У меня есть несколько вопросов по поводу использования Go's sync.Mutex с struct.Например, если бы у меня было struct:

type something struct {
    aMux sync.Mutex
    a    map[string]interface{}

    bMux sync.Mutex
    b    int
}

... , было бы безопасно заблокировать bMux и получить доступ к b, одновременно блокируя aMux идоступ к a без состояния гонки?

Возможно, также полезно знать, что я обращаюсь к указателям на структуры и использую такие методы, чтобы блокировать / разблокировать мьютексы одновременно:

func (s *something) addA(k string, v interface{}) {
    (*s).aMux.Lock()
    (*s).a[k] = v
    (*s).aMux.Unlock()
}

func (s *something) addB(k string, v interface{}) {
    (*s).bMux.Lock()
    (*s).b++
    (*s).bMux.Unlock()
}

Я предполагаю, что это теоретически должно быть безопасно, так как вы уже можете заблокировать мьютекс в структуре, не имея доступа к полям, которые он блокирует. Но при разыменовании struct, как указано выше, Go копирует все значения из struct (что делает его небезопасным), или он только изменяет / извлекает указанные вами поля?

Я бы очень хотел сохранить мьютексы в одной и той же структуре, поскольку в моем коде у меня есть несколько (до шести) связанных полей в одной и той же структуре, которые я блокирую по отдельности мьютексами. Если наличие нескольких мьютексов в одной структуре (для связанных полей) безопасно, но не рекомендуется или является плохой практикой, почему?Какая структура будет лучше?

Ответы [ 2 ]

0 голосов
/ 14 февраля 2019
  • Да, вы можете иметь более одного мьютекса в своих структурах
  • Не усложняйте вещи: вы можете использовать один мьютекс для защиты доступа к любому из двух элементов в вашей структуре, т.е.любая операция, которая изменяет ваш map или int, может использовать один и тот же мьютекс
  • При ссылке на вашу структуру из других функций - используйте указатели, как это делают ваши методы - чтобы гарантировать, что структура не скопирована.Скопированные структуры - с мьютексами - приведут к непредсказуемым / небезопасным результатамПакет (то есть sync.Mutux) не должен копироваться.
0 голосов
/ 14 февраля 2019

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

Вам не нужна явная разыменование,Go делает это за вас:

func (s *something) addA(k string, v interface{}) {
    s.aMux.Lock()
    s.a[k] = v
    s.aMux.Unlock()
}

Должно работать так же хорошо (это в Go tour ).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...