【问题标题】:golang fifo buffered channelgolang fifo 缓冲通道
【发布时间】:2016-08-30 04:14:19
【问题描述】:

据我了解:当通道已满时,GO 中的缓冲通道不是 FIFO。
我的应用程序中需要这种行为(FIFO 行为)。
我怎样才能实现这种行为?有什么开源的吗?
在此先感谢

编辑:
有些人不喜欢这个问题,所以让我说得更清楚:
我的意思是当缓冲通道已满并且多个发送者被阻止时
在尝试将项目添加到频道时,它们将被释放的顺序
不是先进先出。你也可以阅读这个讨论:https://github.com/golang/go/issues/11506

是的,我一直在寻找实现该行为的第三方库。
抱歉没有说清楚。

【问题讨论】:

  • 正如你刚才所说,这就是 Go 中通道的工作方式。您可以通过使用频道来实现这一点......对不起,但绝对是可怕的问题。
  • @evanmcdonnal 未指定在完整通道上阻止的发件人的执行顺序。问如何制作这个FIFO并不可怕。规范中没有任何内容表明您可以通过使用频道来实现这一点......问题的问题是它要求推荐一个软件包。
  • @KarrotKake 不,我认为它很清楚地说明了项目是按照发送顺序从频道中读取的,这意味着先进先出。
  • @evanmcdonnal 规范和内存模型文档没有说明发送时阻塞的 goroutines 的执行顺序。
  • 我将问题编辑得更清楚。很抱歉从一开始就不是这样

标签: go channel fifo


【解决方案1】:

Go 中的缓冲通道始终是 FIFO。规范清楚地说:

通道充当先进先出队列。

如果来自通道的值不是 FIFO,那么这是通道实现中的错误。

以下代码应始终按正确顺序打印 1、2、3、4:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int, 3)
    ch <- 1
    ch <- 2
    ch <- 3

    go func() {
        ch <- 4
    }()

    time.Sleep(time.Second)

    for i := 0; i < 4; i++ {
        fmt.Println(<-ch)
    }
}

Playground link

请注意,当有多个并发发送者时,不保证先发送哪个值。如果有多个等待发送者并且有人从通道缓冲区中删除了一个元素(或者在无缓冲通道的情况下,尝试从通道接收),运行时将随机选择一个发送 goroutine。

例子:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch := make(chan int, 2)
    ch <- 1

    go func() {
        ch <- 2
    }()

    go func() {
        ch <- 3
    }()

    time.Sleep(time.Second)

    for i := 0; i < 3; i++ {
        fmt.Println(<-ch)
    }
}

Playground link

如果您多次运行此代码,您会看到输出有时会是 1、2、3 或 1、3、2。(这在操场上不起作用,因为输出已缓存)

【讨论】:

  • 我的意思是在有多个发件人的情况下,不能保证第一个被阻止的发件人会第一个被释放。这就是我说“当通道已满时,GO 中的缓冲通道不是 FIFO”时的意思。无论如何,我正在寻找 Fifo 阻止发件人的实现。
  • @user3142398 如果你想要这个,你必须自己实现它。我不知道有什么包可以做到这一点。您可能可以使用队列和条件变量以及递增计数器进行发送,但它可能不是很有效。
【解决方案2】:

你可以使用链表。

容器/列表包 (https://golang.org/pkg/container/) 实现了一个可以用作队列的双向链表。也许,它还实现了 Heap,它允许您创建具有优先级的队列。总之,最简单的方法是链表IHMO:

queue := list.New()

queue.PushBack("Hello ") // Enqueue
queue.PushBack("world!")

for queue.Len() > 0 {
    e := queue.Front() // First element
    fmt.Print(e.Value)

    queue.Remove(e) // Dequeue
}

【讨论】:

    猜你喜欢
    • 2020-09-03
    • 2019-10-26
    • 2014-09-26
    • 2016-10-08
    • 2018-07-03
    • 2017-07-22
    • 2014-01-30
    • 2016-11-19
    • 2020-08-09
    相关资源
    最近更新 更多