如何通知另一个goroutine停止?

时间:2019-10-17 23:36:32

标签: go

我有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)
  ...
}

我知道上面的代码并不安全,但是如果我使用通道从gf发送止损,则f将在从该通道读取时被阻止,这就是我想避免。 Go中执行此操作的安全且惯用的方法是什么?

2 个答案:

答案 0 :(得分:2)

使用通道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。

答案 1 :(得分:1)

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

所以f看起来像这样:

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