go - 如果 goroutine 正在运行,则停止它
问题描述
我有一个类似于How to stop a goroutine with a small twist 的问题。我不确定 goroutine 是否正在运行。
var quit = make(chan bool)
func f1() {
go func() {
t := time.NewTimer(time.Minute)
select {
case <-t.C:
// Do stuff
case <-quit:
return
}
}()
}
func f2() {
quit <- true
}
如果f2()
在 之后不到一分钟被调用f1()
,则 goroutine 返回。但是,如果它在一分钟后被调用,goroutine 将已经返回并f2()
阻塞。如果 goroutine 正在运行,我想f2()
取消它,否则什么也不做。
我在这里想要实现的是当且仅当它没有在创建后的一分钟内被取消时才执行任务。
说明:
- 没有什么可以阻止
f2()
被多次调用。 - 一次只运行一个 goroutine。的调用者
f1()
将确保每分钟调用它不超过一次。
解决方案
使用上下文。
f1
使用可能被取消的上下文运行。f2
使用相关的取消功能运行。
func f1(ctx context.Context) {
go func(ctx context.Context) {
t := time.NewTimer(time.Minute)
select {
case <-t.C:
// Do stuff
case <-ctx.Done():
return
}
}(ctx)
}
func f2(cancel context.CancelFunc) {
cancel()
}
稍后,为了协调这两个功能,您可以这样做:
ctx, cancel := context.WithCancel(context.Background())
f1(ctx)
f2(cancel)
您还可以尝试使用该context.WithTimeout
函数来合并外部定义的超时。
如果你不知道是否有一个 goroutine 已经在运行,你可以像上面一样初始化ctx
和cancel
变量,但不要将它们传递给任何东西。这避免了必须检查nil
.
请记住将 ctx 和 cancel 视为要复制的变量,而不是引用,因为您不希望多个 goroutine 共享内存 - 这可能会导致竞争条件。
推荐阅读
- javascript - 如何使用startsWith过滤和获取每个对象键的值?
- php - 如何确保 Laravel 单一身份验证?
- powershell - using module $PSScriptRoot: is not a valid value for using name
- r - 有效地将 XML 转换为数据框
- python - 获取变量的变化率
- wcf - 未触发 Global.asax 方法
- python-3.x - 使用 --user 选项后的 Docker 权限错误
- objective-c - 在 iOS 13 中使用自定义高度呈现模态
- php - 如何在零停机时间的水平扩展设置中使用 Laravel 迁移?
- javascript - 列表打开或关闭时如何添加加减号?