Получение блокировки по адресу памяти вместо переменной в golang

#go #locking #mutex #heap-memory #goroutine

#Вперед #блокировка #мьютекс #куча-память #goroutine

Вопрос:

У меня есть интерфейс под названием Setter. Структура с именем SetterImpl реализует этот интерфейс и имеет 2 установщика, каждый из которых устанавливает 2 интерфейса.

 type Setter interface {
    A() *AInterface
    B() *BInterface
}
type SetterImpl struct {
    a *AInterface
    b *BInterface
}

func (s *SetterImpl) A(a *AInterface) {
    a = a
}

func (s *SetterImpl) B(b *AInterface) {
    b = b
}

func returnSetter(a *AInterface, b *BInterface) Setter {
    return amp;SetterImpl{a:a, b:b}
}
  

Установщик, возвращаемый вышеуказанным методом, находится в куче (скажем, в куче) и отправляется на сервер gRPC. Теперь я хочу обновить a и b в SetterImpl таким образом, чтобы сервер gRPC использовал новые значения.

Итак, теперь у меня есть 2 подпрограммы; одна — основная подпрограмма сервера gRPC (скажем, MAIN), другая — разветвленная (скажем, РАЗВЕТВЛЕННАЯ), которая просто предназначена для обновления полей настройки.

Если я использую Мьютекс в FORKED, это, по сути, добавляет забор (например, java). На самом деле он не блокирует никаких переменных (кроме самого себя). Я не хочу, чтобы MAIN мог читать a и b, хранящиеся в SHeap, пока FORKED обновляет их. Потоки API (подпрограммы) на сервере не получают мьютекс чтения перед чтением значений в SHeap. Итак, возможно ли вообще сделать то, чего я пытаюсь достичь? Если да, то как мне этого добиться?

Комментарии:

1. Я не уверен, что здесь означает «SHeap», но блокировка адреса памяти — это не то, что вы должны пытаться. Мьютексы работают только в том случае, если все участники используют блокировку; main должен получить блокировку перед чтением разделяемой памяти.

2. Похоже, у вас сильный опыт работы с Java, и вы, возможно, переносили слишком много этого опыта в свое программирование на Go. Go сильно отличается от Java; хотя синтаксис внешне похож, хороший код Go работает и написан совсем по-другому. Стандартный шаблон интерфейса Java / impl очень неудобен. Программы и потоки не эквивалентны, и ни один из них не эквивалентен разветвлению процесса. Каналы предпочтительнее блокировки, когда это возможно, а когда нет, мьютексы являются механизмом блокировки.

Ответ №1:

Я не думаю, что вы можете заблокировать переменные в Go. Вы можете заблокировать только раздел кода.

 m.Lock()
// do stuff
m.Unlock()
  

Вы создаете проблему для себя из ничего, используя шаблон «интерфейс» против «Impl».

Вы можете упростить свою жизнь, просто используя обычную функцию. Затем вы можете поместить блокировку внутри функции и гарантировать, что она будет защищена.

Поскольку вы создаете интерфейс, вы не можете ничего гарантировать относительно содержимого функции, которая реализует интерфейс.

Ответ №2:

Переменные не могут быть заблокированы. Итак, то, что я пытаюсь сделать, невозможно. Обходной путь, который я сделал, заключался в добавлении a RWMutex в SetterImpl и выполнении

 mux.RLock()
defer mux.RUnlock()
  

в геттерах a и b в SetterImpl. И когда я хочу установить a и b в РАЗВЕТВЛЕННОМ, я использовал

 mux.Lock()
defer mux.Unlock()
  

Таким образом, если блокировка записи приобретается с помощью FORKED, блокировка чтения не может быть получена в это время. Это возможно, поскольку поле RWLock, созданное в SHeap, используется как глобальная переменная (т. Е. Этот мьютекс никогда не изменяется и передается в РАЗВЕТВЛЕННОМ виде)