【问题标题】:How to implement pop -> do something -> push for a queue using goroutines如何实现 pop -> 做某事 -> 使用 goroutines 推送队列
【发布时间】:2014-09-24 12:02:24
【问题描述】:

我有一个队列,我想执行以下操作:

  • 弹出第一个元素

  • 如果元素是偶数,推元素+1

这应该一直持续到队列为空;此外,我想同时使用多个 goroutine。

我可以为单个 goroutine 做,但是一旦我添加了一段时间,一切都会出错,因为似乎创建了太多的 goroutine。即使放置else {return} 也无法解决问题。附带问题:为什么不呢?我得到错误:

syntax error: unexpected semicolon or newline before else
syntax error: unexpected }

Link to Playground

var list = []int{0, 1, 2, 3}

var mutex = &sync.Mutex{}

func pop(out chan int) {
    mutex.Lock()
    element := list[0]
    fmt.Println("element is ", element)
    list = list[1:]
    mutex.Unlock()
    out <- element
}

func push(in chan int) {
    for element := range in {
        if element%2 == 0 {
            mutex.Lock()
            list = append(list, element+1)
            fmt.Println("New list is ", list)
            mutex.Unlock()
        }
    }
}

func main() {
    out := make(chan int)
    fmt.Println("MAIN")

//  for len(list) != 0 {
    go pop(out)
    go push(out)
//}
    time.Sleep(2)
}

【问题讨论】:

  • 附加问题的答案:您忘记了return 后面的分号,else 必须与前面的} 在同一行。
  • 不需要分号,但正如@tomwilde 所说,else 必须在 } 之后,在同一行中。

标签: concurrency go queue goroutine


【解决方案1】:

一个(缓冲的)通道是一个队列,而不是堆栈。因此,在这种情况下推送和弹出没有意义。

堆栈是 LIFO(后进先出),就像旅行行李箱一样 - 你先把需要的东西放在最后。队列是先进先出的(先进先出),就像你推动弹珠通过的管子。

在队列的上下文中,据说您将元素入队和出队。

考虑到这一切,这就是我解释你想做的事情:

  • 创建一个缓冲通道(缓冲意味着它可以容纳许多元素,有效地使其成为一个队列)。
  • 然后用一堆随机数填充它
  • 对其进行迭代并再次将那些偶数加入队列,将它们加 1。

尝试实现这个新算法。

【讨论】:

  • 对不起,我的意思是队列,但我使用了堆栈名称。
  • 我已经实施了你的建议here(有一个新问题),即使我不喜欢我必须决定队列限制这一事实。
【解决方案2】:

您的代码存在多个问题。

  • else 始终与if 的右大括号位于同一行。请在此阅读the Spec

  • time.Sleeptime.Duration 作为其参数,以纳秒为单位。如果你想睡 2 秒,请使用time.Sleep(2*time.Second)

  • for range 不需要推送。

  • 你的 for 只是一遍又一遍地生成数百万个 goroutine。 Goroutintes 是轻量级的,但不是免费的。添加某种同步机制来控制您正在运行的 goroutines 的数量。

Here 是一个稍微好一点的版本。它可以工作,即使使用 time.Sleep 作为同步机制是你永远不应该做的事情。

【讨论】:

  • 所以基本上只是在 for 中添加一个非常小的等待时间,我们让一些例程在生成大量例程之前完成?另外,您是否建议使用一个全局变量来跟踪周围有多少例程?
  • @meto 没有等待时间。显式同步机制。告诉你是否需要更多 goroutines 的东西。
  • 我明白了。我想知道为什么你的例子没有问题。这是因为短暂的等待时间让一些例程关闭而不是不断跨越新的例程?
  • @meto 基本上,是的。您的代码创建 goroutine 的速度如此之快,以至于它们都没有真正完成这项工作。我的代码之所以有效,是因为它创建它们的速度更慢,从而给了被创建者时间去做他们的事情。
猜你喜欢
  • 2014-08-12
  • 2021-12-06
  • 1970-01-01
  • 2020-06-29
  • 1970-01-01
  • 1970-01-01
  • 2018-07-12
  • 1970-01-01
  • 2019-07-03
相关资源
最近更新 更多