Що таке розмір буфера каналу?


86

Я намагаюся створити асинхронний канал, і я дивився на http://golang.org/ref/spec#Making_slices_maps_and_channels .

c := make(chan int, 10)         // channel with a buffer size of 10

Що означає, що розмір буфера становить 10? Що конкретно представляє / обмежує розмір буфера?


Дивіться тут і далі
Іван Чорний

Дивіться тут також корисно. Дуже прямо і легко зрозуміти :)
Арді Нусаван,

Відповіді:


161

Розмір буфера - це кількість елементів, які можна надіслати на канал без блокування відправки. За замовчуванням канал має розмір буфера 0 (ви отримуєте це за допомогою make(chan int)). Це означає, що кожне надсилання буде блокуватися, доки інша програма не отримає від каналу. Канал буфера розміром 1 може містити 1 елемент до відправки блоків, так що ви отримаєте

c := make(chan int, 1)
c <- 1 // doesn't block
c <- 2 // blocks until another goroutine receives from the channel

21
Хороша відповідь. У Effective Go є приємна глава під назвою "Паралельність", яка викладається на каналах. Настійно рекомендується: golang.org/doc/effective_go.html
Леві

Попсувавшись із цим і make (chan int, 1) дозволяє передавати в мій канал 3 значення перед блокуванням (тестуючи це за допомогою log.Printlns), а за замовчуванням пускає 2 перед блокуванням. Будь-яка ідея, чому:
Маурісіо

@Mauricio Це звучить досить дивно. Я щойно тестував, використовуючи Go 1.8.3 локально, а також використовуючи функцію "Спробувати Go" на golang.org , і в обох випадках він все ще поводиться так, як це задокументовано у моїй відповіді.
Лілі Баллард,

1
Я вдячний за відгук, але насправді неправильно трактував друк даних на консолі. Це працює, як ви описали.
Маурісіо

10

Наступний код ілюструє блокування небаферованого каналу:

// to see the diff, change 0 to 1
c := make(chan struct{}, 0)
go func() {
    time.Sleep(2 * time.Second)
    <-c
}()
start := time.Now()
c <- struct{}{} // block, if channel size is 0
elapsed := time.Since(start)
fmt.Printf("Elapsed: %v\n", elapsed)

Ви можете пограти з кодом тут .


0
package main

import (
    "fmt"
    "time"
)

func receiver(ch <-chan int) {
    time.Sleep(500 * time.Millisecond)
    msg := <-ch
    fmt.Printf("receive messages  %d from the channel\n", msg)
}

func main() {
    start := time.Now()
    zero_buffer_ch := make(chan int, 0)
    go receiver(zero_buffer_ch)
    zero_buffer_ch <- 444
    elapsed := time.Since(start)    
    fmt.Printf("Elapsed using zero_buffer channel: %v\n", elapsed)

    restart := time.Now()
    non_zero_buffer_ch := make(chan int, 1)
    go receiver(non_zero_buffer_ch)
    non_zero_buffer_ch <- 4444
    reelapsed := time.Since(restart)
    fmt.Printf("Elapsed using non zero_buffer channel: %v\n", reelapsed)
}

результат:

отримувати повідомлення 444 від каналу

За минуле за допомогою каналу zero_buffer: 505,6729 мс

Минуло, використовуючи не нульовий_буферний канал: 0 с

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.