我有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
到f
发送止损,则f
将在从该通道读取时被阻止,这就是我想避免。 Go中执行此操作的安全且惯用的方法是什么?
答案 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()
}
}