英文:
How to block all goroutines except the one running
问题
我有两个(但稍后会有三个)go例程,它们正在处理来自远程服务器(来自ampq通道)的传入消息。但是因为它们在处理相同的数据/状态,我希望阻塞除正在运行的例程之外的所有其他go例程。
我想出了一个解决方案,使用chan bool
,其中每个go例程都会阻塞然后释放它,代码如下:
package main
func a(deliveries <-chan amqp, handleDone chan bool) {
for d := range deliveries {
<-handleDone // 数据始终到达,等待其他通道
handleDone <- false // 阻塞其他通道
// 处理数据...
handleDone <- true // 我完成了,其他通道可以做任何事情
}
}
func b(deliveries <-chan amqp, handleDone chan bool) {
for d := range deliveries {
<-handleDone
handleDone <- false
// 处理数据...
handleDone <- true
}
}
func main() {
handleDone := make(chan bool, 1)
go a(arg1, handleDone)
go b(arg2, handleDone)
// go c(arg3, handleDone) , 稍后
handleDone <- true // 启动
}
但是第一次每个函数都会得到handleDone <- true
,它们将被执行。稍后,如果我添加另一个第三个函数,情况将变得更加复杂。如何阻塞除正在运行的例程之外的所有其他go例程?是否有其他更好的解决方案?
英文:
I have two (but later I'll be three) go routines that are handling incoming messages from a remote server (from a ampq channel). But because they are handling on the same data/state, I want to block all other go routines, except the one running.
I come up with a solution to use chan bool
where each go routine blocks and then release it, the code is like:
package main
func a(deliveries <-chan amqp, handleDone chan bool) {
for d := range deliveries {
<-handleDone // Data comes always, wait for other channels
handleDone <- false // Block other channels
// Do stuff with data...
handleDone <- true // I'm done, other channels are free to do anything
}
}
func b(deliveries <-chan amqp, handleDone chan bool) {
for d := range deliveries {
<-handleDone
handleDone <- false
// Do stuff with data...
handleDone <- true
}
}
func main() {
handleDone := make(chan bool, 1)
go a(arg1, handleDone)
go b(arg2, handleDone)
// go c(arg3, handleDone) , later
handleDone <- true // kickstart
}
But for the first time each of the function will get handleDone <- true
, which they will be executed. And later if I add another third function, things will get more complicated. How can block all other go routines except the running? Any other better solutions?
答案1
得分: 6
你想要查看sync包。
你可以使用互斥锁来实现。
英文:
You want to look at the sync package.
You would do this with a mutex.
答案2
得分: 3
如果您有一条消息的输入流,并且有三个goroutine在监听和处理该流,而且您希望确保一次只有一个goroutine在运行,解决方案非常简单:终止两个goroutine。
您正在启动并发并增加复杂性,然后尝试阻止它们同时运行。最终结果与单个流读取器相同,但可能会出现许多问题。
英文:
If you have an incoming stream of messages and you have three goroutines listening on that stream and processing and you want to ensure that only one goroutine is running at a time, the solution is quite simple: kill off two of the goroutines.
You're spinning up concurrency and adding complexity and then trying to prevent them from running concurrently. The end result is the same as a single stream reader, but with lots of things that can go wrong.
答案3
得分: 2
我很困惑为什么你想要这个 - 为什么不能独立处理deliveries
上的每个消息?为什么有两个不同的函数处理这些消息?如果每个函数负责特定类型的消息,似乎你想要一个deliveries
接收器,根据类型将其分派到适当的逻辑。
但是回答你的问题,我不认为每个函数在开始时都会从handleDone
接收到true
。一个函数(假设是a
)接收到从main
发送的true
;另一个函数(然后是b
)接收到第一个函数发送的false
。因为你丢弃了接收到的值,所以你无法知道这一点。然后两个函数都在运行,并且你正在使用缓冲通道(你可能想要使用make(chan bool)
来代替非缓冲通道),所以会产生混乱,特别是当你添加第三个goroutine时。
handleDone <- false
实际上没有实现任何功能。只需将handleDone
上的任何值视为接力比赛中的接力棒。一旦goroutine接收到这个值,它就可以执行相应的操作;完成后,它应该将其发送到通道以将其传递给下一个goroutine。
英文:
I'm puzzled why you want this - why can't each message on deliveries
be handled independently? and why are there two different functions handling those message? If each is responsible for a particular type of message, it seems like you want one deliveries
receiver that dispatches to appropriate logic for the type.
But to answer your question, I don't think it's true that each function will get a true
from handleDone
on start. One (let's say it's a
) is receiving the true
sent from main
; the other (b
then) is getting the false
sent from the first. Because you're discarding the value received, you can't tell this. And then both are running, and you're using a buffered channel (you probably want make(chan bool)
instead for an unbuffered one), so confusion ensues, particularly when you add that third goroutine.
The handleDone <- false
doesn't actually accomplish anything. Just treat any value on handleDone
as the baton in a relay race. Once a goroutine receives this value, it can do its thing; when it's done, it should send it to the channel to hand it to the next goroutine.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论