gpt4 book ai didi

go - 为什么我的 channel 需要缓冲区?

转载 作者:IT王子 更新时间:2023-10-29 01:23:07 25 4
gpt4 key购买 nike

我正在尝试学习 Go,并且正在使用 this tutorial .

我写了下面的代码,

var wg sync.WaitGroup

func foo(c chan int, someValue int) {
defer wg.Done()
c <- someValue * 5
}

func main() {
fooVal := make(chan int)
for i := 0; i < 10; i++ {
go foo(fooVal, i)
wg.Add(1)
}

wg.Wait() // Wait for all routines to complete
close(fooVal) // close channel

for item := range fooVal {
fmt.Println(item)
}
}

这是我目前的理解,

  • 我创建了一个接收整数的 channel
  • 我创建了 10 个子例程,并将 1 个添加到 WaitGroup ,以便稍后让它们同步
  • 我等待例程完成
  • 我关闭 channel ,使其不再接收任何值
  • 我循环遍历 channel 中的值以打印它们

但是,我收到一条错误消息:

fatal error: all goroutines are asleep - deadlock!

我不确定这是什么意思。我的猜测是 range 试图从 channel 中获取值,但它没有任何值。但这不应该发生,因为我等待所有例程完成,然后关闭了 channel 。

这是怎么回事?

对此的解决方案是执行类似make(chan int, 10) 的操作来为其提供一个缓冲区,但我不确定缓冲区是什么或我为什么需要它。

另外,我不确定 make 做了什么。我也用它来创建 map 。它只是一个构造函数吗?

最佳答案

您所有的 goroutine 都处于 sleep 状态的原因是因为默认情况下, channel 会在发送时阻止它的 goroutine,直到接收到值。参见 https://tour.golang.org/concurrency/2

By default, sends and receives block until the other side is ready. This allows goroutines to synchronize without explicit locks or condition variables.

缓冲区通过允许一个 channel 在不阻塞的情况下“保存”那么多值来解决这个问题。将缓冲 channel 想象成一个可以容纳 N 项的桶(其中 N 是缓冲区大小,在您的情况下为 10)以便将更多内容放入桶中,您需要等待删除某些内容(即读取)。默认情况下, channel 是无缓冲的,并且必须先接收到它的值,然后才能解除阻塞它正在发送的 goroutine。

在你的代码中,你有 goroutines 试图将项目放入你的无缓冲 channel ,所以第一个例程等待它放入 channel 的项目被读取。但是在 range 语句读取它之前你的 channel 永远不会清空,它永远不会触发直到 channel 清空并且 goroutine 完成(因为 wg.Wait()),这是一个死锁。两者都无法继续。

有了缓冲区,缓冲 channel 会告诉您的 goroutine 可以在不读取它的值的情况下完成(在您的情况下最多 10 个项目),因此 WaitGroup 完成,范围语句按预期读取所有值。

至于make,把它当成一个构造函数就够了,但要知道它只用于 slice 、 channel 和贴图。这些是 go 中的特殊类型,不能像常规结构一样创建。 (我认为这与这些行为中的每一个都具有通用性这一事实有关,即它可以容纳任何指定类型的项目,这就是为什么需要 make 的原因,但我不是 100% 如此)。

关于go - 为什么我的 channel 需要缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51530320/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com