【问题标题】:How to block all goroutines except the one running如何阻止除正在运行的所有 goroutines
【发布时间】:2013-03-03 04:52:50
【问题描述】:

我有两个(但以后我会是三个)go 例程处理来自远程服务器(来自 ampq 通道)的传入消息。但是因为它们正在处理相同的数据/状态,所以我想阻止所有其他 go 例程,除了正在运行的例程。

我想出了一个使用chan bool的解决方案,其中每个goroutine阻塞然后释放它,代码是这样的:

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
}

但是第一次每个函数都会得到handleDone &lt;- true,它们将被执行。稍后如果我添加另一个第三个函数,事情会变得更加复杂。如何阻止除运行之外的所有其他 go 例程?还有其他更好的解决方案吗?

【问题讨论】:

  • 我不认为你的频道做你认为他们做的事,因为你从来没有检查收到的价值。无论如何,使用缓冲通道作为互斥体/信号量可能是危险的。请改用实际的 Mutex。
  • 请注意,它们被称为“goroutines”,而不是“goroutines”。这是因为“例程”一词可能指任何过程 PL 中的任何过程/函数,因此“go 例程”听起来像“Go 中的例程”,这使得该术语的预期含义消失了。

标签: go


【解决方案1】:

你想看看同步包。

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

你可以使用互斥锁来做到这一点。

【讨论】:

    【解决方案2】:

    如果你有一个传入的消息流,并且有三个 goroutine 监听该流并进行处理,并且你想确保一次只有一个 goroutine 在运行,那么解决方案非常简单:杀死两个 goroutine。

    您正在提高并发性并增加复杂性,然后试图阻止它们同时运行。最终结果与单个流读取器相同,但有很多可能出错的地方。

    【讨论】:

      【解决方案3】:

      我很困惑你为什么想要这个 - 为什么不能独立处理deliveries 上的每条消息?为什么有两个不同的函数处理这些消息?如果每个人都负责一种特定类型的消息,那么您似乎需要一个 deliveries 接收器来分派到该类型的适当逻辑。

      但要回答您的问题,我认为每个函数在开始时都不会从handleDone 获得true。一个(假设它是a)正在接收从main 发送的true;另一个(b then)正在获取从第一个发送的false。因为您正在丢弃收到的值,所以您无法分辨这一点。然后两者都在运行,并且您正在使用缓冲通道(您可能希望 make(chan bool) 代替无缓冲通道),因此会出现混乱,尤其是当您添加第三个 goroutine 时。

      handleDone &lt;- false 实际上并没有完成任何事情。只需将handleDone 上的任何值视为接力赛中的接力棒。一旦一个 goroutine 接收到这个值,它就可以做它的事情;完成后,它应该将其发送到通道以将其交给下一个 goroutine。

      【讨论】:

      • 感谢您的评论。我已经更改了部分代码。我删除了falses。但它现在堆栈,它只是等待在那里。它只是在两个 go 函数中等待&lt;-handleDone。似乎他们没有从主要方面得到真实的。
      • main 在做什么?到达handleDone &lt;- true了吗?
      • 问题是,handleDone &lt;- true 之后,func a() 只是等待func b(),但在我的情况下,func b() 根本无法执行。我想要的只是在任何时候,如果其中一个 goroutine(a()b() 等)正在运行,而其他所有程序都应该等到运行完成。
      • 啊,对。当我建议不要使用缓冲通道时,我把你误入歧途了。在这种情况下,缓冲实际上是有意义的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-25
      • 1970-01-01
      • 2021-10-22
      • 2016-10-28
      • 2019-10-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多