【问题标题】:Stopping other goroutines conditionally有条件地停止其他 goroutine
【发布时间】:2021-02-27 03:55:18
【问题描述】:

我怀疑我所有生成的 goroutine 是否在完成分配的工作后都死掉了。 我必须进行两次 HTTP 调用(总是),但基于一个标志,读取其中任何一个的响应。 到目前为止我所做的是 ->

    var result error
    resultChannel := make(chan error)

    var wg sync.WaitGroup
    wg.Add(1)  // only adding 1, as I don't need to wait for other to complete.

    go func() {
        _, err := // HTTP call ONE
        if flagIsTrue {
            defer wg.Done()
            resultChannel <- err
        }
    }()
    go func() {
        _, err :=  // HTTP call TWO
        if !flagIsTrue {
            defer wg.Done()
            resultChannel <- err
        }
    }()

    go func() {
        wg.Wait()
        close(resultChannel)
    }()

    for err := range resultChannel {
        result = err
    }

因此,我将等待相应的呼叫,并只听它的响应。这工作得很好,但是由于应用程序部署在服务器上,我猜主 goroutine 不会死(此后杀死其他 goroutine),我主要关心的是其他可忽略的线程是否会死HTTP 调用的响应(afaik,我们需要告诉 go 一个 goroutine 需要死掉)。 我的担忧:

  1. 假设(对我来说确实如此)主线程在执行这些调用之一后不会终止。
  2. 可忽略(响应是,但必须触发 API 调用)线程会死吗?
  3. 我是否应该使用选择案例来处理这个问题,如果是,那么如何处理(欢迎其他建议)?

【问题讨论】:

  • 您的示例没有显示flagIsTrue 的来源或设置方式,这对于您的示例是否正常至关重要。一般来说,在通道上发送的 goroutine 也应该负责关闭它。
  • @super 该标志是在生成 goroutine 之前设置的。另外,通道要关闭了,我担心goroutine。
  • 如果标志从未改变,这应该是安全的,因为只有一个 goroutine 写入结果通道。然而,它确实提出了一个问题,为什么你有一个等待组。为什么不简单地在 resultchannel 上接收一个值并继续前进?
  • @super 我想我误解了并发的概念,你能解释一下为什么不写入通道会确保这是安全的。我的印象是 goroutine 仍然存在。对于后续点,您是否建议创建一个 goroutie,进行两个 API 调用,然后根据标志将响应写入通道。
  • 当一个goroutine执行的函数结束时,这个goroutine就不再活着。因此,在您的示例中,如果 goroutine 不写入结果通道,它将简单地停止。另一方面,如果它尝试写入 resultChannel,它将阻塞并等待,直到有人在另一端接收到值,从而保持活动状态。但是尝试在关闭的通道上发送也会引起恐慌,因此根据经验,写入方应该负责关闭通道。

标签: go concurrency channel goroutine


【解决方案1】:

如果在创建 goroutine 之前设置了 flagIsTrue,那么只有一个 goroutine 可以写入通道。另一个不会尝试写入通道,因此将终止。

你可以简单地将标志的检查移到外面,然后根据标志创建一个 goroutine。

【讨论】:

  • 是的,标志是在生成 goroutine 之前设置的,在当前情况下,只有一个在通道中写入。如果我要创建一个 goroutine,我应该在这个 goroutine 中同时调用两个 API 吗?
  • 一个带有 if flag { url1 } else {url2} 的 goroutine 应该这样做
  • 有必要进行两个 API 调用。阅读响应是有条件的。您是否建议创建一个 goroutie,进行两个 API 调用,然后根据标志将响应写入通道
  • 如果您必须同时调用两个 API 调用,那么您所做的是正确的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-29
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-09
  • 2011-10-12
相关资源
最近更新 更多