如何阻止除正在运行的协程之外的所有协程

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

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 &lt;-chan amqp, handleDone chan bool) {
	for d := range deliveries {
		&lt;-handleDone        // Data comes always, wait for other channels
		handleDone &lt;- false // Block other channels

		// Do stuff with data...

		handleDone &lt;- true // I&#39;m done, other channels are free to do anything
	}
}

func b(deliveries &lt;-chan amqp, handleDone chan bool) {
	for d := range deliveries {
		&lt;-handleDone
		handleDone &lt;- false
		// Do stuff with data...
		handleDone &lt;- true
	}
}

func main() {
	handleDone := make(chan bool, 1)
	go a(arg1, handleDone)
	go b(arg2, handleDone)
	// go c(arg3, handleDone) , later

	handleDone &lt;- true // kickstart
}

But for the first time each of the function will get handleDone &lt;- 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包。

http://golang.org/pkg/sync/

你可以使用互斥锁来实现。

英文:

You want to look at the sync package.

http://golang.org/pkg/sync/

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 &lt;- 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.

huangapple
  • 本文由 发表于 2013年3月15日 01:24:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/15416071.html
匿名

发表评论

匿名网友

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

确定