Согласно Tour of Go
Отправка в буферный блок канала только при заполнении буфера.Получает блок, когда буфер пуст.
Итак, в этом случае вы создаете буферизованный канал, используя длину 5000.
for i := 1; i <= maxDepth; i++ {
fmt.Println(i)
q, nq = nq, make(map[string]int)
for word := range q { // for each word
if _, ok := vis[word]; !ok { // if not visited visit
wg.Add(1) // add a worker
vis[word] = true
go threading(queue, word) // fetch in concurrent manner
for v := range queue { // <<< blocks here when queue is empty
fmt.Println(v)
for _, w := range v {
nq[w] = i
}
}
}
}
}
Как видите, япрокомментировал в коде, после 1-й итерации цикл for будет блокироваться, пока канал не станет пустым.В этом случае после извлечения jump
Он отправляет массив, соответствующий подобным словам, но после этого, поскольку цикл for блокируется, поскольку zerkems объясняет, что вы не перейдете к следующей итерации (i = 2).В конечном итоге вы можете закрыть канал, чтобы завершить блокировку цикла for.Но так как вы используете один и тот же канал для записи нескольких процедур, он будет паниковать, если вы закроете его из нескольких программ.
Чтобы преодолеть это, мы можем найти хороший обходной путь.
- Мы точно знаем, сколько невидимых элементов мы выбираем.
- Теперь мы знаем, где находится блок
Сначала нам нужно посчитать не посещенные слова, а затем мы можем повторить стольковремени
vis := make(map[string]bool)
queue := make(chan []string, 5000)
for i := 1; i <= maxDepth; i++ {
fmt.Println(i)
q, nq = nq, make(map[string]int)
unvisited := 0
for word := range q {
if _, ok := vis[word]; !ok {
vis[word] = true
unvisited++
wg.Add(1)
go threading(queue, word)
}
}
wg.Wait() // wait until jobs are done
for j := 0; j < unvisited; j++ { // << does not block as we know how much
v := <-queue // we exactly try to get unvisited amount
fmt.Println(v)
for _, w := range v {
nq[w] = i
}
}
}
В этой ситуации мы просто подсчитываем минимальные итерации, которые нам нужно пройти, чтобы получить результаты.Кроме того, вы можете видеть, что я переместился вниз по внешнему циклу for и использовал оригинальный, чтобы просто добавить слова к работникам.Он будет запрашивать выборку всех слов и будет ждать в следующем цикле неблокируемого завершения задач.
Последний цикл ждет, пока все рабочие не будут выполнены.После этой следующей итерации могут быть достигнуты работы и следующий уровень BFS.
Сводка
- Распределение рабочей нагрузки
- Ожидание результатов
- Не делайте оба одновременно
Надеюсь, это поможет.