【问题标题】:When to use a buffered channel?何时使用缓冲通道?
【发布时间】:2013-02-13 08:06:39
【问题描述】:

缓冲通道的用例是什么?如果我想要多个并行操作,我可以使用默认的同步通道 eq。

package main
import "fmt"
import "time"

func longLastingProcess(c chan string) {
    time.Sleep(2000 * time.Millisecond)
    c <- "tadaa"
}

func main() {
    c := make(chan string)
    go longLastingProcess(c)
    go longLastingProcess(c)
    go longLastingProcess(c)
    fmt.Println(<- c)
}

增加缓冲区大小的实际情况是什么?

【问题讨论】:

    标签: go


    【解决方案1】:

    如果通道的接收者总是比发送者慢,任何大小的缓冲区最终都会被消耗掉。这将为您留下一个像无缓冲通道一样经常暂停您的 goroutine 的通道,因此您不妨使用无缓冲通道。

    如果接收器通常比发送器快(除了偶尔的突发),则缓冲通道可能会有所帮助,并且应将缓冲区设置为您可以在运行时通过测量获得的典型突发的大小。

    作为缓冲通道的替代方案,最好只通过通道发送数组或包含数组的结构来处理突发/批处理。

    【讨论】:

      【解决方案2】:

      通常,出于性能原因,通道中的缓冲是有益的。

      如果一个程序是使用事件流或数据流方法设计的,通道为事件在一个进程和另一个进程之间传递提供了手段(我使用术语 process 的含义相同就像 Tony Hoare 的 Communicating Sequential Processes (CSP) 中一样,即实际上是 goroutine 的同义词。

      • 有时程序需要其组件保持锁步同步。在这种情况下,需要无缓冲的通道。

      • 否则,向通道添加缓冲通常是有益的。这应该被视为一个优化步骤(如果没有设计出来,仍然可能出现死锁)。

      • 通过使用带有小缓冲区的通道 (example),可以实现新颖的节流结构。

      • occamjcsp 中使用了特殊的覆盖或有损形式的通道,用于修复进程循环(或循环)的特殊情况否则可能会陷入僵局。这在 Go 中也可以通过编写覆盖 goroutine 缓冲区 (example) 来实现。

      您不应该仅仅为了修复死锁而添加缓冲。如果您的程序死锁,从零缓冲开始并考虑依赖关系会更容易修复。然后当你知道它不会死锁时添加缓冲。

      您可以组合地构造 goroutines - 也就是说,goroutines 本身可能包含 goroutines。这是 CSP 的一个特性,极大地有利于可扩展性。在将组的外部使用设计为自包含组件时,一组 goroutine 之间的内部通道并不重要。这个原则可以在越来越大的范围内重复应用。

      【讨论】:

      • 它们也可以用来确保一个 goroutine 退出,例如在time.After 中,它被用于无论客户端是否在等待值,它都可以发送和返回。例如,缓冲也被使用。 os/signal 包的客户端,因为 API 无法阻止通知。
      【解决方案3】:

      给出一个更具体的用例:

      假设您希望您的通道表示一个任务队列,以便任务调度程序可以将作业发送到队列中,并且工作线程可以通过在通道中接收作业来使用它。

      进一步假设,尽管通常您希望及时处理每个作业,但工作人员完成任务所需的时间比调度程序安排它所花费的时间要长。

      拥有一个缓冲区允许调度程序将作业存放在队列中,并且仍然保持对用户输入(或网络流量或其他任何内容)的响应,因为它不必在每次调度任务时等待工作人员准备好之前休眠。相反,它开展自己的业务,并相信工人会在较安静的时期迎头赶上。

      如果你想要一个更具体的例子来处理特定的软件,那么我会看看我能做什么,但我希望这能满足你的需求。

      【讨论】:

      • 嗨,亲爱的朋友。目前我正在寻找一个处理特定软件的具体示例。如果您有任何链接文章或代码可以帮助我深入了解我应该在哪里使用 goroutines 和通道来在我的 golang 项目中实现并发。我真的很感激。
      【解决方案4】:

      这是一个难题,因为程序不正确:它在收到一个 goroutine 的信号后退出,但启动了三个。缓冲通道使其没有什么不同。

      编辑:例如,这里有一些关于频道buffers 的一般性讨论。还有一些exercise。和book chapter 差不多。

      【讨论】:

      • 嘿,问题是关于缓冲通道的实际使用场景。上面的例子实际上只是一个例子。
      • 使用缓冲通道很大程度上取决于执行的任务。查看更新的答案。
      【解决方案5】:

      只要还有空间,缓冲通道对发送方来说是非阻塞的。这可以提高响应速度和吞吐量。

      在一个缓冲通道上发送多个项目可确保按照发送顺序对其进行处理。

      来自 Effective Go(示例):“A buffered channel can be used like a semaphore, for instance to limit throughput.

      一般来说,频道使用的用例和模式有很多,所以这不是一个令人筋疲力尽的答案。

      【讨论】:

        猜你喜欢
        • 2014-01-30
        • 2016-06-20
        • 2020-10-23
        • 2021-10-13
        • 2014-10-28
        • 2017-09-06
        • 2016-08-30
        • 1970-01-01
        • 2019-01-07
        相关资源
        最近更新 更多