英文:
How to implement pop -> do something -> push for a queue using goroutines
问题
我有一个队列,我想执行以下操作:
-
弹出第一个元素
-
如果元素是偶数,将元素+1后推入队列
这应该一直进行,直到队列为空;此外,我想同时使用多个goroutine。
我可以为单个goroutine做到这一点,但是一旦我添加了一个while循环,一切就都出错了,因为似乎创建了太多的goroutine。即使加上else {return}
也无法解决问题。附带问题:为什么不行?我得到以下错误:
语法错误:else之前的意外分号或换行符
语法错误:}
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 }
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)
}
答案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 – 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 asif
's closing brace. Please read the Spec on this. -
time.Sleep
takestime.Duration
as its argument, which is in nanoseconds. If you want to sleep for 2 seconds, usetime.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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论