# #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")
}