如何使用goroutines实现队列的pop -> do something -> push操作?

huangapple go评论84阅读模式
英文:

How to implement pop -> do something -> push for a queue using goroutines

问题

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

  • 弹出第一个元素

  • 如果元素是偶数,将元素+1后推入队列

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

我可以为单个goroutine做到这一点,但是一旦我添加了一个while循环,一切就都出错了,因为似乎创建了太多的goroutine。即使加上else {return}也无法解决问题。附带问题:为什么不行?我得到以下错误:

语法错误:else之前的意外分号或换行符
语法错误:}

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)
    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("新列表是", list)
            mutex.Unlock()
        }
    }
}

func main() {
    out := make(chan int)
    fmt.Println("主函数")

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

I have a queue and I would like to perform the following operations:

  • pop the first element

  • If the element is even, push element +1

This should go on until the queue is empty; furthermore I want to use multiple goroutines at the same time.

I am able to do for a single goroutine, but as soon as I add a while everything goes wrong, since it appears that too many goroutines are created. Even putting a else {return} will not solve the problem. Side question: why not? I get the errors:

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

Link to Playground

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

var mutex = &amp;sync.Mutex{}

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

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

func main() {
	out := make(chan int)
	fmt.Println(&quot;MAIN&quot;)

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

答案1

得分: 4

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

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

在队列的上下文中,你可以将元素入队(enqueue)和出队(dequeue)。

考虑到这一切,我理解你想要做以下操作:

  • 创建一个缓冲通道(缓冲意味着它可以容纳多个元素,实际上使其成为一个队列)。
  • 然后用一堆随机数填充它。
  • 遍历它,并且只将偶数再次入队,同时将它们加1。

尝试实现这个新算法。

英文:

A (buffered) channel is a queue, not a stack. Hence pushing and popping don't make sense in that context.

Stacks are LIFO (last in, first out), like travel luggage &ndash; you put in last what you need first. Queues are FIFO (first in, first out), like a tube where you push marbles through.

In the context of queues, you're said to enqueue and dequeue elements.

Considering all this, this is what I interpret you'd like to do:

  • Create a buffered channel (buffered means that it can hold a number of elements, effectively making it a queue).
  • Then fill it up with a bunch of random numbers
  • Iterate over it and enqueue again only those that are even, adding 1 to them.

Try to implement this new algorithm.

答案2

得分: 2

你的代码存在多个问题。

  • else 总是与 if 的闭合括号在同一行。请阅读规范中的相关内容。

  • time.Sleep 接受 time.Duration 作为参数,单位为纳秒。如果你想要休眠2秒,可以使用 time.Sleep(2*time.Second)

  • push 函数中的 for range 不是必需的。

  • 你的 for 循环一直在不断地创建数百万个 goroutine。Goroutine 虽然轻量级,但并非免费。添加某种同步机制来控制你运行的 goroutine 数量。

这里是一个稍微改进的版本。它可以工作,尽管使用 time.Sleep 作为同步机制是不推荐的做法。

英文:

Multiple problems with your code.

  • else is always on the same line as if's closing brace. Please read the Spec on this.

  • time.Sleep takes time.Duration as its argument, which is in nanoseconds. If you want to sleep for 2 seconds, use time.Sleep(2*time.Second).

  • for range in push is not needed.

  • Your for for just spawns millions of goroutines over and over. Goroutintes are lightweight, but not free. Add some kind of synchronisation mechanism to control how many goroutines you are running.

Here is a slightly better version. It works, even though using time.Sleep as a synchronisation mechanism is something you should never do.

huangapple
  • 本文由 发表于 2014年9月24日 20:02:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/26016406.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定