Зацикливание параллельно - PullRequest
0 голосов
/ 24 июня 2018

Я новичок в golang и читаю пример из книги gopl .

Существует пример параллельного создания миниатюр:

func makeThumbnails6(filenames <-chan string) int64 {
    sizes := make(chan int64)
    var wg sync.WaitGroup // number of working goroutines
    for f := range filenames {
        wg.Add(1)
        // worker
        go func(f string) {
            defer wg.Done()
            thumb, err := thumbnail.ImageFile(f)
            if err != nil {
                log.Println(err)
                return
            }
            info, _ := os.Stat(thumb) // OK to ignore error
            sizes <- info.Size()
        }(f)
    }

    // closer
    go func() {
        wg.Wait()
        close(sizes)
    }()

    var total int64
    for size := range sizes {
        total += size
    }
    return total
}

Мое сомнение в том, что, возможно, что ближе пройдет wg.Wait() до того, как все файлы будут обработаны?

Например, если work1 завершит свою работу и уменьшит wg до нуля, тогда произойдет какое-то волшебное планированиеи close получите время для запуска и закрытия канала?

Любая помощь приветствуется!

1 Ответ

0 голосов
/ 24 июня 2018

wg.Wait не вернется, пока не будут выполнены все рабочие программы. Когда wg.Wait вызывается в более близкой подпрограмме, вы уже вызывали wg.Add(1) один раз для каждой рабочей подпрограммы, поэтому wg.Wait не вернется, пока wg.Done не будет вызвано такое же количество раз, и это происходит, когда функция goroutine возвращает. Следовательно, более близкая программа не будет вызывать close, пока все рабочие программы не завершат свою работу.

Как вы сказали, теоретически возможно, что счетчик wg может достигать 0, пока он еще находится в цикле, который создает рабочих, но как только цикл завершится, счетчик будет иметь значение 0 только после завершения всех процедур. Поскольку вы не запускаете более близкую программу, пока цикл не завершится, нет опасности возврата wg.Wait до того, как все рабочие закончат.

...