【问题标题】:How do I notify another goroutine to stop? [duplicate]如何通知另一个 goroutine 停止? [复制]
【发布时间】:2020-02-14 22:19:36
【问题描述】:

我有 2 个 goroutine,g 用于检测 f 应该停止的条件,f 在进行实际处理之前检查它是否应该在每次迭代中停止。在 Java 等其他语言中,我会使用线程安全的共享变量,如以下代码:

func g(stop *bool) {
  for {
    if check_condition() {
      *stop = true
      return
    }
  }
}

func f(stop *bool) {
  for {
    if *stop {
      return
    }
    do_something()
  }
}

func main() {
  var stop = false
  go g(&stop)
  go f(&stop)
  ...
}

我知道上面的代码不安全,但是如果我使用通道将停止从g 发送到ff 在从通道读取时会被阻止,这是我想要避免的。在 Go 中执行此操作的安全且惯用的方法是什么?

【问题讨论】:

    标签: go


    【解决方案1】:

    使用 channel close 来通知其他 goroutine 一个条件。在检查条件时使用带有默认子句的 select 以避免阻塞。

    func g(stop chan struct{}) {
        for {
            if check_condition() {
                close(stop)
                return
            }
        }
    }
    
    func f(stop chan struct{}) {
        for {
            select {
            case <-stop:
                return
            default:
                do_something()
            }
        }
    }
    
    func main() {
        var stop = make(chan struct{})
        go g(stop)
        go f(stop)
    }
    

    它也可以向容量大于零的通道发送值,但关闭通道会扩展到支持多个 goroutine。

    【讨论】:

      【解决方案2】:

      方法是使用带有默认子句的 select 语句(请参阅this example)。

      所以f 看起来像:

      func f(stop chan bool) {
        select {
          case s := <- stop:
            if s {
              return
            }
          default:
            do_something()
        }
      }
      

      【讨论】:

      • 这会在g 发送停止之前阻止f
      • 抱歉,我理解错了。
      • 不,它不会阻塞。这是做你想做的事的规范方式。当你想让 f 停止 doing_something 时,将 true 推入停止通道。
      猜你喜欢
      • 2011-10-12
      • 2017-07-19
      • 1970-01-01
      • 2019-08-10
      • 2018-04-24
      • 2020-04-03
      • 2016-11-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多