通道缓冲区大小是多少?


Answers:


157

缓冲区大小是可以在不发送阻塞的情况下发送到通道的元素数。默认情况下,通道的缓冲区大小为0(可通过来获得此值make(chan int))。这意味着每个发送都会阻塞,直到另一个goroutine从通道接收到为止。缓冲区大小为1的通道可以容纳1个元素,直到发送块为止,因此您将获得

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

21
好答案。有效的Go在频道上有一个很好的标题为“并发”的章节。强烈推荐:golang.org/doc/effective_go.html
Levi's

我搞砸了这个和make(chan int,1)允许在阻塞之前将3个值传递到我的通道中(用log.Printlns测试),默认值是在阻塞之前让2进入。任何想法为什么:
Mauricio

@Mauricio听起来很奇怪。我刚刚在本地使用Go 1.8.3进行了测试,还使用了golang.org上的“ Try Go”功能,在两种情况下,它的行为均仍如我的答案中所述。
莉莉·巴拉德

1
我感谢您的答复,但实际上是在误解将数据打印到控制台的情况。它确实按您描述的那样工作。
Mauricio

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.6729ms

使用非zero_buffer通道经过的时间:0s

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.