Ваш мониторНачало никогда не умирает. Когда все рабочие закончатся, он продолжает ждать на cs. Это взаимоблокировки, потому что больше ничего не будет отправлено на cs, и поэтому wg никогда не достигнет 0. Возможно, решение заключается в том, чтобы монитор закрывал канал, когда все рабочие заканчивают. Если цикл for находится в основном, он завершит цикл, вернется из основного и закончит программу.
Например: http://play.golang.org/p/nai7XtTMfr
package main
import (
"fmt"
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, cs chan string, i int) {
defer wg.Done()
cs <- "worker" + strconv.Itoa(i)
}
func monitorWorker(wg *sync.WaitGroup, cs chan string) {
wg.Wait()
close(cs)
}
func main() {
wg := &sync.WaitGroup{}
cs := make(chan string)
for i := 0; i < 10; i++ {
wg.Add(1)
go worker(wg, cs, i)
}
go monitorWorker(wg, cs)
for i := range cs {
fmt.Println(i)
}
}
Edit: Это ответ на первый комментарий OP в.
Ваша программа имеет три части, которые необходимо синхронизировать. Во-первых, всем вашим работникам необходимо отправить данные. Затем ваш цикл печати должен распечатать эти данные. Затем ваша основная функция должна возвращать, тем самым заканчивая программу. В вашем примере все работники отправляют данные, все данные печатаются, но сообщение никогда не отправляется на главную, чтобы оно возвращалось изящно.
В моем примере, главным образом, печать и «monitorWorker» просто показывают основную информацию, когда она получила каждый кусочек данных, который требуется распечатать. Таким образом, программа заканчивается изящно, а не тупиком.
Если вы настаиваете на том, чтобы контур печати находился в другом горку, вы можете это сделать. Но тогда дополнительное сообщение должно быть отправлено на главную, чтобы оно вернулось. В следующем примере я использую канал для обеспечения основных целей при печати всех данных.
package main
import (
"fmt"
"strconv"
"sync"
)
func worker(wg *sync.WaitGroup, cs chan string, i int) {
defer wg.Done()
cs <- "worker" + strconv.Itoa(i)
}
func monitorWorker(wg *sync.WaitGroup, cs chan string) {
wg.Wait()
close(cs)
}
func printWorker(cs <-chan string, done chan<- bool) {
for i := range cs {
fmt.Println(i)
}
done <- true
}
func main() {
wg := &sync.WaitGroup{}
cs := make(chan string)
for i := 0; i < 10; i++ {
wg.Add(1)
go worker(wg, cs, i)
}
go monitorWorker(wg, cs)
done := make(chan bool, 1)
go printWorker(cs, done)
<-done
}
Спасибо за помощь. Но это не решает мою проблему параллельной обработки. В моем случае monitorWorker должен работать параллельно (например, печать с канала). – vrbilgi
@vrbilgi, я прокомментировал ответ. –
Я пробовал разные варианты, но ваш ответ прост и элегантен. Thk: D – vrbilgi