Каналы рутины и "остановка короткая"

Я читаю / работаю с шаблонами 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, чтобы запретить бесконечную блокировку горутин.

Другие вопросы по тегам