Каналы рутины и "остановка короткая"
Я читаю / работаю с шаблонами Go Concurrency: конвейеры и отмена, но у меня возникают проблемы с пониманием короткого раздела " Остановка ". У нас есть следующие функции:
func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
func merge(cs ...<-chan int) <-chan int {
var wg sync.WaitGroup
out := make(chan int, 1) // enough space for the unread inputs
// Start an output goroutine for each input channel in cs. output
// copies values from c to out until c is closed, then calls wg.Done.
output := func(c <-chan int) {
for n := range c {
out <- n
}
wg.Done()
}
wg.Add(len(cs))
for _, c := range cs {
go output(c)
}
// Start a goroutine to close out once all the output goroutines are
// done. This must start after the wg.Add call.
go func() {
wg.Wait()
close(out)
}()
return out
}
func main() {
in := gen(2, 3)
// Distribute the sq work across two goroutines that both read from in.
c1 := sq(in)
c2 := sq(in)
// Consume the first value from output.
out := merge(c1, c2)
fmt.Println(<-out) // 4 or 9
return
// Apparently if we had not set the merge out buffer size to 1
// then we would have a hanging go routine.
}
Теперь, если вы заметили строку 2
в merge
говорит, что мы делаем chan
с buffer
размер 1, потому что это достаточно места для непрочитанных вводов. Тем не менее, я почти уверен, что мы должны выделить chan
с buffer
размер 2. В соответствии с этим примером кода:
c := make(chan int, 2) // buffer size 2
c <- 1 // succeeds immediately
c <- 2 // succeeds immediately
c <- 3 // blocks until another goroutine does <-c and receives 1
Поскольку этот раздел подразумевает, что chan
из buffer
размер 3 не будет блокировать. Кто-нибудь может уточнить / помочь в моем понимании?
1 ответ
Программа отправляет два значения в канал out
и читает одно значение из канала out
, Одно из значений не получено.
Если канал не буферизован (емкость 0), то одна из отправляющих программ будет блокироваться до выхода из программы. Это утечка.
Если канал создан с пропускной способностью 1, то обе программы могут отправить на канал и выйти. Первое значение, отправленное на канал, получено main
, Второе значение остается в канале.
Если основная функция не получает значение из канала out
затем необходим канал с пропускной способностью 2, чтобы запретить бесконечную блокировку горутин.