Может ли группа ожидания использоваться с обычными функциями

# #go #concurrency

Вопрос:

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

 type Manager struct {
   ....
   wg sync.WaitGroup
}

func (m *Manager) create() {
    m.wg.Add(1)
    defer m.wg.Done()
    ....
    ....
}
func (m *Manager) close() {
   m.wg.Wait()
}
 

Это отлично работает для меня, я просто хочу знать, правильно ли это

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

1. Не уверен, о чем вы спрашиваете. Если вы используете группу ожидания в контексте без параллельного кода, на самом деле в этом нет никакого смысла. Это было бы похоже на использование мьютекса без необходимости синхронизации.

2. Я не знаю, имеет ли это смысл. Если create() и close() вызываются последовательно (в одной и той же подпрограмме), имеет ли смысл ждать close() create() ? В любом случае он делает это последовательно.

3. Это не так , но и не правильно . Это все равно что беспокоиться о том, могут ли ваши пингвины быть фиолетовыми, когда у вас нет пингвинов.

4. Опубликованный вами код не является правильным использованием групп ожидания. Вы вызываете Done в конце функции create, поэтому гарантированно, что ждать будет нечего. Если бы менеджер создал одну или несколько подпрограмм go в create (позволяя каждой подпрограмме go вызывать, когда она была завершена), тогда этот шаблон имел бы больше смысла.

Ответ №1:

В параллельном контексте группа ожидания позволяет остановить подпрограмму до тех пор, пока группа не будет «завершена». Если вы неправильно используете группу ожидания, у вас могут быть эти ошибочные результаты:

  • Done Меньше Add : Группа ожидания никогда не заканчивается, и ожидающая подпрограмма останавливается навсегда (либо паникует, если все подпрограммы заблокированы, либо в противном случае происходит молчаливый сбой).
  • Меньше Add , чем Done : паника. Видеть WaitGroup.Add

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

Может быть допустимый случай использования, когда вы хотите увеличить / уменьшить счетчик, а затем проверить, что он был разрешен до 0 в конце. В не параллельном контексте вам не нужен такой модный инструмент для этого: просто используйте int !

Например:

 var counter int
// setup
// vv equivalent to wg.Add
counter  = expectedNumberOfActions

for x := range actions {
    // do something
    // vv equivalent to wg.Done
    counter--
}

// vv achieves the purpose of wg.Wait
if counter != 0 {
   panic("oh no! the counter was not resolved correctly. there may be some bug in the implementation")
}